/** * Broadcast.java * * Created on Oct 14, 2010, 4:47:24 PM * * @author pquiring * * This class implements Broadcasting a pre-recorded message to a list of phone numbers and/or taking surveys. * * NOTE : Please only broadcast to your own customers. Laws in some countries/states may prohibit contacting random individuals. * */ import java.io.*; import java.net.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; import javaforce.*; import javaforce.voip.*; public class Broadcast extends javax.swing.JFrame implements SIPClientInterface, RTPInterface, ActionListener { public final String version = "0.36"; public String startList = null; public String cfgSuffix = ""; public boolean allowdups = false; public JFLockFile lockFile; public String databaseName = "jfBroadcastSchema2"; public String dbPath; /** Creates new form Broadcast */ public Broadcast() { processArgs(); lockFile = new JFLockFile(); if (!lockFile.lock(JF.getUserPath() + "/jfbroadcast" + cfgSuffix + ".lck")) { JF.showError("Error", "Another instance of jfBroadcast is already running!"); System.exit(0); } dbPath = null; if (dbPath == null) { dbPath = System.getProperty("user.home"); } //setup derby.system.home System.setProperty("derby.system.home", dbPath); SQL.initClass(SQL.derbySQL); initComponents(); setPosition(); loadHelp(); if (cfgSuffix.length() > 0) setTitle("jfBroadcast/" + version + ":" + cfgSuffix); else setTitle("jfBroadcast/" + version); JFLog.init(JF.getUserPath() + "/jfbroadcast" + cfgSuffix + ".log", true); loadSetup(); setOptsState(); updateAvailableLists(); new Thread() { @Override public void run() { createDatabase(); if (check_update.isSelected()) checkVersion(); } }.start(); idx = 0; buttonGroup1.add(single); buttonGroup1.add(multi); buttonGroup1.add(terminate); buttonGroup1.add(gotouser); buttonGroup1.add(cont); buttonGroup1.add(gotoidx); buttonGroup1.add(xfer); loadQuestion(); if (startList != null) { //do -start command line option int cnt = selected_list.getItemCount(); boolean ok = false; for(int b=0;b<cnt;b++) { String item = (String)selected_list.getItemAt(b); if (item.equals(startList)) { selected_list.setSelectedIndex(b); start.doClick(); ok = true; break; } } if (!ok) { JFLog.log("Error:specifed list for -start option not found"); } } //set icons JFImage appicon = new JFImage(); appicon.loadPNG(this.getClass().getClassLoader().getResourceAsStream("jfbroadcast.png")); setIconImage(appicon.getImage()); appicon.loadPNG(this.getClass().getClassLoader().getResourceAsStream("jfbroadcast_tray.png")); tray = SystemTray.getSystemTray(); Dimension size = tray.getTrayIconSize(); JFImage scaled = new JFImage(size.width, size.height); scaled.fill(0, 0, size.width, size.height, 0x00000000, true); //fill with alpha transparent if (true) { //scaled image (looks bad sometimes) scaled.getGraphics().drawImage(appicon.getImage() , 0, 0, size.width, size.height , 0, 0, appicon.getWidth(), appicon.getHeight() , null); } else { //center image scaled.getGraphics().drawImage(appicon.getImage() , (size.width - appicon.getWidth()) / 2 , (size.height - appicon.getHeight()) / 2 , null); } //create tray icon PopupMenu popup = new PopupMenu(); show = new MenuItem("Show"); show.addActionListener(this); popup.add(show); popup.addSeparator(); exit = new MenuItem("Exit"); exit.addActionListener(this); popup.add(exit); icon = new TrayIcon(scaled.getImage(), "jfBroadcast", popup); icon.addActionListener(this); tray = SystemTray.getSystemTray(); try { tray.add(icon); } catch (Exception e) { JFLog.log(e); } } /** 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") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { buttonGroup1 = new javax.swing.ButtonGroup(); jLabel1 = new javax.swing.JLabel(); start = new javax.swing.JButton(); status = new javax.swing.JLabel(); jTabbedPane1 = new javax.swing.JTabbedPane(); jPanel2 = new javax.swing.JPanel(); jLabel9 = new javax.swing.JLabel(); jLabel10 = new javax.swing.JLabel(); jLabel11 = new javax.swing.JLabel(); jLabel12 = new javax.swing.JLabel(); sip_user = new javax.swing.JTextField(); sip_auth = new javax.swing.JTextField(); sip_host = new javax.swing.JTextField(); jLabel34 = new javax.swing.JLabel(); sip_start = new javax.swing.JTextField(); jLabel36 = new javax.swing.JLabel(); sip_end = new javax.swing.JTextField(); jLabel35 = new javax.swing.JLabel(); sip_name = new javax.swing.JTextField(); sip_pass = new javax.swing.JPasswordField(); jPanel3 = new javax.swing.JPanel(); create_list = new javax.swing.JButton(); list_name = new javax.swing.JTextField(); jLabel5 = new javax.swing.JLabel(); selected_list = new javax.swing.JComboBox(); reset_list = new javax.swing.JButton(); delete_list = new javax.swing.JButton(); export_list = new javax.swing.JButton(); import_list = new javax.swing.JButton(); fix_list = new javax.swing.JButton(); jLabel33 = new javax.swing.JLabel(); jButton2 = new javax.swing.JButton(); jPanel11 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); listView = new javax.swing.JTable(); jPanel4 = new javax.swing.JPanel(); jPanel1 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); greeting_threshold = new javax.swing.JTextField(); silence_threshold = new javax.swing.JTextField(); silence_duration = new javax.swing.JTextField(); human_vm_detect = new javax.swing.JCheckBox(); voicemail_hangup = new javax.swing.JCheckBox(); jPanel7 = new javax.swing.JPanel(); jLabel13 = new javax.swing.JLabel(); enable_g729a = new javax.swing.JCheckBox(); enable_reinvites = new javax.swing.JCheckBox(); jLabel6 = new javax.swing.JLabel(); maxRingTime = new javax.swing.JSpinner(); enable_g711u = new javax.swing.JCheckBox(); enable_g711a = new javax.swing.JCheckBox(); number_lines = new javax.swing.JSpinner(); jLabel24 = new javax.swing.JLabel(); jLabel23 = new javax.swing.JLabel(); delay = new javax.swing.JSpinner(); check_update = new javax.swing.JCheckBox(); maxAttempts = new javax.swing.JSpinner(); exit_on_close_window = new javax.swing.JCheckBox(); jPanel8 = new javax.swing.JPanel(); xfer_number = new javax.swing.JTextField(); jLabel7 = new javax.swing.JLabel(); xfer_digit = new javax.swing.JTextField(); enable_xfer = new javax.swing.JCheckBox(); jPanel9 = new javax.swing.JPanel(); jPanel10 = new javax.swing.JPanel(); jLabel26 = new javax.swing.JLabel(); day1 = new javax.swing.JCheckBox(); start1 = new javax.swing.JTextField(); jLabel25 = new javax.swing.JLabel(); end1 = new javax.swing.JTextField(); day2 = new javax.swing.JCheckBox(); start2 = new javax.swing.JTextField(); jLabel27 = new javax.swing.JLabel(); end2 = new javax.swing.JTextField(); day3 = new javax.swing.JCheckBox(); start3 = new javax.swing.JTextField(); jLabel28 = new javax.swing.JLabel(); end3 = new javax.swing.JTextField(); day4 = new javax.swing.JCheckBox(); start4 = new javax.swing.JTextField(); jLabel29 = new javax.swing.JLabel(); end4 = new javax.swing.JTextField(); end5 = new javax.swing.JTextField(); jLabel30 = new javax.swing.JLabel(); start5 = new javax.swing.JTextField(); day5 = new javax.swing.JCheckBox(); day6 = new javax.swing.JCheckBox(); start6 = new javax.swing.JTextField(); jLabel31 = new javax.swing.JLabel(); end6 = new javax.swing.JTextField(); day7 = new javax.swing.JCheckBox(); start7 = new javax.swing.JTextField(); jLabel32 = new javax.swing.JLabel(); end7 = new javax.swing.JTextField(); jPanel5 = new javax.swing.JPanel(); enable = new javax.swing.JCheckBox(); wav_filename = new javax.swing.JTextField(); select_file = new javax.swing.JButton(); next_msg = new javax.swing.JButton(); prev_msg = new javax.swing.JButton(); title = new javax.swing.JLabel(); single = new javax.swing.JRadioButton(); count = new javax.swing.JComboBox(); multi = new javax.swing.JRadioButton(); terminate = new javax.swing.JRadioButton(); gotouser = new javax.swing.JRadioButton(); goto_1 = new javax.swing.JTextField(); goto_2 = new javax.swing.JTextField(); goto_3 = new javax.swing.JTextField(); goto_4 = new javax.swing.JTextField(); goto_5 = new javax.swing.JTextField(); goto_6 = new javax.swing.JTextField(); goto_7 = new javax.swing.JTextField(); goto_8 = new javax.swing.JTextField(); goto_9 = new javax.swing.JTextField(); jLabel8 = new javax.swing.JLabel(); jLabel14 = new javax.swing.JLabel(); jLabel15 = new javax.swing.JLabel(); jLabel16 = new javax.swing.JLabel(); jLabel17 = new javax.swing.JLabel(); jLabel18 = new javax.swing.JLabel(); jLabel19 = new javax.swing.JLabel(); jLabel20 = new javax.swing.JLabel(); jLabel21 = new javax.swing.JLabel(); cont = new javax.swing.JRadioButton(); gotoidx = new javax.swing.JRadioButton(); gotoidxnum = new javax.swing.JTextField(); jLabel22 = new javax.swing.JLabel(); msg_idx = new javax.swing.JSlider(); xfer = new javax.swing.JRadioButton(); jPanel6 = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); help = new javax.swing.JTextArea(); save_setup = new javax.swing.JButton(); jButton1 = new javax.swing.JButton(); setTitle("jfBroadcast"); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { formWindowClosing(evt); } }); jLabel1.setText("Broadcast a message to a list of phone numbers or take a survey."); start.setText("Start!"); start.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { startActionPerformed(evt); } }); status.setText("Status:OK"); jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("SIP Details")); jLabel9.setText("Username"); jLabel10.setText("Authorization Username"); jLabel10.setToolTipText("optional"); jLabel11.setText("Domain"); jLabel12.setText("Password"); jLabel34.setText("SIP Port Range:"); jLabel34.setToolTipText("Valid range : 1024 thru 65535"); sip_start.setText("6000"); sip_start.setToolTipText("1024 - 60000"); jLabel36.setText("to"); sip_end.setText("9000"); sip_end.setToolTipText("1024 - 65535"); jLabel35.setText("Display Name"); jLabel35.setToolTipText("optional"); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addComponent(jLabel34) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sip_start, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel36) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sip_end, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 465, Short.MAX_VALUE)) .addGroup(jPanel2Layout.createSequentialGroup() .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel10) .addComponent(jLabel9) .addComponent(jLabel35) .addComponent(jLabel11) .addComponent(jLabel12)) .addGap(25, 25, 25) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(sip_auth) .addComponent(sip_name) .addComponent(sip_user) .addComponent(sip_host) .addComponent(sip_pass, javax.swing.GroupLayout.Alignment.LEADING)))) .addContainerGap()) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel35) .addComponent(sip_name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel9) .addComponent(sip_user, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel10) .addComponent(sip_auth, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel11) .addComponent(sip_host, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel12) .addComponent(sip_pass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(sip_start, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel36) .addComponent(sip_end, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel34)) .addContainerGap(204, Short.MAX_VALUE)) ); jTabbedPane1.addTab("SIP", jPanel2); jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Lists")); create_list.setText("Create List..."); create_list.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { create_listActionPerformed(evt); } }); list_name.setText("default"); jLabel5.setText("Select List:"); selected_list.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { selected_listItemStateChanged(evt); } }); reset_list.setText("Reset List..."); reset_list.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { reset_listActionPerformed(evt); } }); delete_list.setText("Delete List..."); delete_list.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { delete_listActionPerformed(evt); } }); export_list.setText("Export List..."); export_list.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { export_listActionPerformed(evt); } }); import_list.setText("Import List..."); import_list.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { import_listActionPerformed(evt); } }); fix_list.setText("Fix 'calling' in List..."); fix_list.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { fix_listActionPerformed(evt); } }); jLabel33.setText("Name:"); jButton2.setText("Fix 'errors' in List..."); jButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(evt); } }); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(selected_list, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(import_list) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(export_list)) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(reset_list) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(delete_list)) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(fix_list) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton2)) .addGroup(jPanel3Layout.createSequentialGroup() .addComponent(jLabel33) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(list_name, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(create_list))) .addContainerGap(371, Short.MAX_VALUE)) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel3Layout.createSequentialGroup() .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(list_name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(create_list) .addComponent(jLabel33)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel5) .addComponent(selected_list, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(import_list) .addComponent(export_list)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(reset_list) .addComponent(delete_list)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(fix_list) .addComponent(jButton2)) .addContainerGap(241, Short.MAX_VALUE)) ); jTabbedPane1.addTab("Lists", jPanel3); listView.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { }, new String [] { "Number", "Status", "Attempts", "Survey", "Timestamp" } ) { Class[] types = new Class [] { java.lang.String.class, java.lang.String.class, java.lang.Integer.class, java.lang.String.class, java.lang.String.class }; boolean[] canEdit = new boolean [] { false, false, false, false, false }; public Class getColumnClass(int columnIndex) { return types [columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); listView.setEnabled(false); jScrollPane1.setViewportView(listView); javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11); jPanel11.setLayout(jPanel11Layout); jPanel11Layout.setHorizontalGroup( jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel11Layout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 686, Short.MAX_VALUE) .addContainerGap()) ); jPanel11Layout.setVerticalGroup( jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel11Layout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 378, Short.MAX_VALUE) .addContainerGap()) ); jTabbedPane1.addTab("Active List", jPanel11); jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Options")); jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Human/Voicemail Detection Options")); jLabel2.setText("Greeting Detection Threshold:"); jLabel2.setToolTipText("100-32000 (default = 1000)"); jLabel3.setText("Silence Detection Threshold:"); jLabel3.setToolTipText("100-32000 (default = 1000)"); jLabel4.setText("Silence Duration (ms):"); jLabel4.setToolTipText("100-5000 (default = 2000)"); greeting_threshold.setText("1000"); greeting_threshold.setToolTipText("100-32000 (default = 1000)"); silence_threshold.setText("1000"); silence_threshold.setToolTipText("100-32000 (default = 1000)"); silence_duration.setText("2000"); silence_duration.setToolTipText("100-5000 (default = 1000)"); human_vm_detect.setSelected(true); human_vm_detect.setText("Enable human/voicemail detection"); human_vm_detect.setToolTipText("Start messages after human/voicemail greeting."); human_vm_detect.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { human_vm_detectActionPerformed(evt); } }); voicemail_hangup.setText("Voicemail hangup"); voicemail_hangup.setToolTipText("Hangup call if voicemail is detected."); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(human_vm_detect) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(voicemail_hangup, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(greeting_threshold, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel3) .addComponent(jLabel4)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(silence_threshold) .addComponent(silence_duration, javax.swing.GroupLayout.PREFERRED_SIZE, 122, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addComponent(human_vm_detect) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(greeting_threshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(silence_threshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(7, 7, 7) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(silence_duration, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(voicemail_hangup) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel7.setBorder(javax.swing.BorderFactory.createTitledBorder("General Options")); jLabel13.setText("Delay (ms) :"); jLabel13.setToolTipText("100-10000"); enable_g729a.setSelected(true); enable_g729a.setText("Enable g729a codec"); enable_reinvites.setSelected(true); enable_reinvites.setText("Enable reinvites"); jLabel6.setText("Number of Lines:"); jLabel6.setToolTipText("Number of concurrent calls."); maxRingTime.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { maxRingTimeStateChanged(evt); } }); enable_g711u.setSelected(true); enable_g711u.setText("Enable g711u codec"); enable_g711a.setText("Enable g711a codec"); number_lines.setValue(4); number_lines.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { number_linesStateChanged(evt); } }); jLabel24.setText("Max Attempts:"); jLabel24.setToolTipText("Max attempts to call each number."); jLabel23.setText("Max Ring Time:"); jLabel23.setToolTipText("Max ring time in seconds."); delay.setToolTipText("100-10000"); delay.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { delayStateChanged(evt); } }); check_update.setSelected(true); check_update.setText("Check for update on startup"); maxAttempts.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { maxAttemptsStateChanged(evt); } }); exit_on_close_window.setText("Close app when closing window"); javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); jPanel7.setLayout(jPanel7Layout); jPanel7Layout.setHorizontalGroup( jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(exit_on_close_window) .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel7Layout.createSequentialGroup() .addComponent(jLabel24) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(maxAttempts)) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel7Layout.createSequentialGroup() .addComponent(jLabel23) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(maxRingTime)) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel7Layout.createSequentialGroup() .addComponent(jLabel13) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(delay)) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel7Layout.createSequentialGroup() .addComponent(jLabel6) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(number_lines, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(enable_g711a) .addComponent(enable_g711u) .addComponent(enable_g729a) .addComponent(check_update) .addComponent(enable_reinvites)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel7Layout.setVerticalGroup( jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel6) .addComponent(number_lines, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel13) .addComponent(delay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(7, 7, 7) .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel23) .addComponent(maxRingTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel24) .addComponent(maxAttempts, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(enable_g729a) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(enable_g711u) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(enable_g711a) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(enable_reinvites) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(check_update) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(exit_on_close_window) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jPanel8.setBorder(javax.swing.BorderFactory.createTitledBorder("Transfer Option")); jLabel7.setText("Transfer destination ="); xfer_digit.setText("0"); enable_xfer.setText("Enable transfer : Digit ="); javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8); jPanel8.setLayout(jPanel8Layout); jPanel8Layout.setHorizontalGroup( jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel8Layout.createSequentialGroup() .addContainerGap() .addComponent(enable_xfer) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(xfer_digit, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel7) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(xfer_number) .addContainerGap()) ); jPanel8Layout.setVerticalGroup( jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel8Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(enable_xfer) .addComponent(xfer_digit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(xfer_number, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel7)) .addContainerGap()) ); javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); jPanel4.setLayout(jPanel4Layout); jPanel4Layout.setHorizontalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel4Layout.createSequentialGroup() .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 136, Short.MAX_VALUE))) .addContainerGap()) ); jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() .addGap(10, 10, 10) .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jTabbedPane1.addTab("Options", jPanel4); jPanel10.setBorder(javax.swing.BorderFactory.createTitledBorder("Calling Times")); jLabel26.setText("List all times in 24HR format."); day1.setText("Sunday"); start1.setText("10:00"); jLabel25.setText("to"); end1.setText("17:00"); day2.setSelected(true); day2.setText("Monday"); start2.setText("10:00"); jLabel27.setText("to"); end2.setText("17:00"); day3.setSelected(true); day3.setText("Tuesday"); start3.setText("10:00"); jLabel28.setText("to"); end3.setText("17:00"); day4.setSelected(true); day4.setText("Wednesday"); start4.setText("10:00"); jLabel29.setText("to"); end4.setText("17:00"); end5.setText("17:00"); jLabel30.setText("to"); start5.setText("10:00"); day5.setSelected(true); day5.setText("Thursday"); day6.setSelected(true); day6.setText("Friday"); start6.setText("10:00"); jLabel31.setText("to"); end6.setText("17:00"); day7.setText("Saturday"); start7.setText("10:00"); jLabel32.setText("to"); end7.setText("17:00"); javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10); jPanel10.setLayout(jPanel10Layout); jPanel10Layout.setHorizontalGroup( jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel10Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel25) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(jLabel26) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel27) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day3) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel28) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel29) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel30) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day6) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel31) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel10Layout.createSequentialGroup() .addComponent(day7) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(start7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel32) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(end7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); jPanel10Layout.setVerticalGroup( jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel10Layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel26) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day1) .addComponent(start1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel25) .addComponent(end1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day2) .addComponent(start2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel27) .addComponent(end2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day3) .addComponent(start3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel28) .addComponent(end3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day4) .addComponent(start4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel29) .addComponent(end4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day5) .addComponent(start5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel30) .addComponent(end5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day6) .addComponent(start6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel31) .addComponent(end6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(day7) .addComponent(start7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel32) .addComponent(end7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9); jPanel9.setLayout(jPanel9Layout); jPanel9Layout.setHorizontalGroup( jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel9Layout.createSequentialGroup() .addContainerGap() .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(493, Short.MAX_VALUE)) ); jPanel9Layout.setVerticalGroup( jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel9Layout.createSequentialGroup() .addContainerGap() .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(143, Short.MAX_VALUE)) ); jTabbedPane1.addTab("Times", jPanel9); jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder("Messages / Questions")); enable.setText("Enable : WAV="); wav_filename.setText("filename.wav"); select_file.setText("..."); select_file.setToolTipText("Select File..."); select_file.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { select_fileActionPerformed(evt); } }); next_msg.setText(">"); next_msg.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { next_msgActionPerformed(evt); } }); prev_msg.setText("<"); prev_msg.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { prev_msgActionPerformed(evt); } }); title.setText("#1/99"); single.setText("Single digit response : allowed responses ="); count.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "1-2", "1-3", "1-4", "1-5", "1-6", "1-7", "1-8", "1-9" })); multi.setText("Long response (user ends input with # or after 5 sec pause) (continues to next message)"); terminate.setText("Terminate call after this message"); gotouser.setText("Goto message from user input (1-99)"); gotouser.setToolTipText("Goto question based on digit pressed."); goto_1.setText("0"); goto_1.setToolTipText("1"); goto_2.setText("0"); goto_2.setToolTipText("2"); goto_3.setText("0"); goto_3.setToolTipText("3"); goto_4.setText("0"); goto_4.setToolTipText("4"); goto_5.setText("0"); goto_5.setToolTipText("5"); goto_6.setText("0"); goto_6.setToolTipText("6"); goto_7.setText("0"); goto_7.setToolTipText("7"); goto_8.setText("0"); goto_8.setToolTipText("8"); goto_9.setText("0"); goto_9.setToolTipText("9"); jLabel8.setText("1:"); jLabel14.setText("3:"); jLabel15.setText("2:"); jLabel16.setText("4:"); jLabel17.setText("5:"); jLabel18.setText("7:"); jLabel19.setText("6:"); jLabel20.setText("9:"); jLabel21.setText("8:"); cont.setSelected(true); cont.setText("Continue to next message"); gotoidx.setText("Goto message after this message (1-99)"); gotoidxnum.setText("0"); jLabel22.setText("(continues to next message)"); msg_idx.setMaximum(98); msg_idx.setValue(0); msg_idx.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { msg_idxStateChanged(evt); } }); xfer.setText("Transfer call after message"); javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); jPanel5.setLayout(jPanel5Layout); jPanel5Layout.setHorizontalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup() .addComponent(enable) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(wav_filename, javax.swing.GroupLayout.DEFAULT_SIZE, 391, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)) .addGroup(jPanel5Layout.createSequentialGroup() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(cont) .addComponent(terminate)) .addGap(249, 249, 249))) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(msg_idx, 0, 0, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup() .addComponent(select_file) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(title, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(prev_msg) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(next_msg)))) .addGroup(jPanel5Layout.createSequentialGroup() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(multi) .addGroup(jPanel5Layout.createSequentialGroup() .addComponent(single) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(count, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel22)) .addGroup(jPanel5Layout.createSequentialGroup() .addComponent(gotoidx) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(gotoidxnum, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel5Layout.createSequentialGroup() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(gotouser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(xfer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel8) .addGap(2, 2, 2) .addComponent(goto_1, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel15) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_2, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel14) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_3, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel16) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_4, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel17) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_5, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel19) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_6, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel18) .addGap(6, 6, 6) .addComponent(goto_7, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel21) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_8, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel20) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(goto_9, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); jPanel5Layout.setVerticalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup() .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(enable) .addComponent(wav_filename, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(next_msg) .addComponent(prev_msg) .addComponent(title) .addComponent(select_file)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel5Layout.createSequentialGroup() .addComponent(cont) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(terminate) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(single) .addComponent(count, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel22))) .addComponent(msg_idx, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(multi) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(gotoidx) .addComponent(gotoidxnum, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(gotouser) .addComponent(goto_1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel8) .addComponent(jLabel15) .addComponent(goto_2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(goto_3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(goto_4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel14) .addComponent(jLabel16) .addComponent(jLabel17) .addComponent(goto_5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(goto_6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(goto_7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(goto_8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel18) .addComponent(jLabel19) .addComponent(jLabel21) .addComponent(jLabel20) .addComponent(goto_9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(xfer) .addContainerGap(177, Short.MAX_VALUE)) ); jTabbedPane1.addTab("Messages / Questions", jPanel5); help.setEditable(false); help.setColumns(20); help.setRows(5); jScrollPane2.setViewportView(help); javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); jPanel6.setLayout(jPanel6Layout); jPanel6Layout.setHorizontalGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 706, Short.MAX_VALUE) ); jPanel6Layout.setVerticalGroup( jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) ); jTabbedPane1.addTab("Help", jPanel6); save_setup.setText("Save Setup"); save_setup.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { save_setupActionPerformed(evt); } }); jButton1.setText("Donate"); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTabbedPane1) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButton1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(save_setup)) .addGroup(layout.createSequentialGroup() .addComponent(start) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(status, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(save_setup) .addComponent(jButton1)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTabbedPane1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(start) .addComponent(status)) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void startActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startActionPerformed if (state == states.CALLING) { stopCalling(); return; } if (state == states.STOPPING) { if (JF.showConfirm("Warning", "Are you sure you want to force stop?")) { forceStopCalling(); } return; } callingThread = new Thread() { @Override public void run() { startCalling(); } }; callingThread.start(); }//GEN-LAST:event_startActionPerformed private void save_setupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_save_setupActionPerformed saveSetup(); }//GEN-LAST:event_save_setupActionPerformed private void msg_idxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_msg_idxStateChanged gotoQuestion(msg_idx.getValue()); }//GEN-LAST:event_msg_idxStateChanged private void prev_msgActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prev_msgActionPerformed prevQuestion(); }//GEN-LAST:event_prev_msgActionPerformed private void next_msgActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_next_msgActionPerformed nextQuestion(); }//GEN-LAST:event_next_msgActionPerformed private void select_fileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_select_fileActionPerformed selectFile(); }//GEN-LAST:event_select_fileActionPerformed private void maxAttemptsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_maxAttemptsStateChanged validateOptions(); }//GEN-LAST:event_maxAttemptsStateChanged private void maxRingTimeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_maxRingTimeStateChanged validateOptions(); }//GEN-LAST:event_maxRingTimeStateChanged private void number_linesStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_number_linesStateChanged validateOptions(); }//GEN-LAST:event_number_linesStateChanged private void delayStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_delayStateChanged validateOptions(); }//GEN-LAST:event_delayStateChanged private void fix_listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fix_listActionPerformed fixList(false, false); }//GEN-LAST:event_fix_listActionPerformed private void import_listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_import_listActionPerformed importList(); }//GEN-LAST:event_import_listActionPerformed private void export_listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_export_listActionPerformed exportList(); }//GEN-LAST:event_export_listActionPerformed private void delete_listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_delete_listActionPerformed deleteList(); }//GEN-LAST:event_delete_listActionPerformed private void reset_listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reset_listActionPerformed resetList(); }//GEN-LAST:event_reset_listActionPerformed private void selected_listItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_selected_listItemStateChanged updateList(); }//GEN-LAST:event_selected_listItemStateChanged private void create_listActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_create_listActionPerformed createList(); }//GEN-LAST:event_create_listActionPerformed private void human_vm_detectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_human_vm_detectActionPerformed setOptsState(); }//GEN-LAST:event_human_vm_detectActionPerformed private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed JF.donate(); }//GEN-LAST:event_jButton1ActionPerformed private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing if (settings.exit_on_close_window) { if (lockFile != null) { lockFile.unlock(); } System.exit(0); } else { icon.displayMessage(null, "jfBroadcast is still active", TrayIcon.MessageType.NONE); } }//GEN-LAST:event_formWindowClosing private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed fixList(false, true); }//GEN-LAST:event_jButton2ActionPerformed /** * @param args the command line arguments */ public static void main(String args[]) { Broadcast.args = args; java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Broadcast().setVisible(true); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JCheckBox check_update; private javax.swing.JRadioButton cont; private javax.swing.JComboBox count; private javax.swing.JButton create_list; private javax.swing.JCheckBox day1; private javax.swing.JCheckBox day2; private javax.swing.JCheckBox day3; private javax.swing.JCheckBox day4; private javax.swing.JCheckBox day5; private javax.swing.JCheckBox day6; private javax.swing.JCheckBox day7; private javax.swing.JSpinner delay; private javax.swing.JButton delete_list; private javax.swing.JCheckBox enable; private javax.swing.JCheckBox enable_g711a; private javax.swing.JCheckBox enable_g711u; private javax.swing.JCheckBox enable_g729a; private javax.swing.JCheckBox enable_reinvites; private javax.swing.JCheckBox enable_xfer; private javax.swing.JTextField end1; private javax.swing.JTextField end2; private javax.swing.JTextField end3; private javax.swing.JTextField end4; private javax.swing.JTextField end5; private javax.swing.JTextField end6; private javax.swing.JTextField end7; private javax.swing.JCheckBox exit_on_close_window; private javax.swing.JButton export_list; private javax.swing.JButton fix_list; private javax.swing.JTextField goto_1; private javax.swing.JTextField goto_2; private javax.swing.JTextField goto_3; private javax.swing.JTextField goto_4; private javax.swing.JTextField goto_5; private javax.swing.JTextField goto_6; private javax.swing.JTextField goto_7; private javax.swing.JTextField goto_8; private javax.swing.JTextField goto_9; private javax.swing.JRadioButton gotoidx; private javax.swing.JTextField gotoidxnum; private javax.swing.JRadioButton gotouser; private javax.swing.JTextField greeting_threshold; private javax.swing.JTextArea help; private javax.swing.JCheckBox human_vm_detect; private javax.swing.JButton import_list; private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel10; private javax.swing.JLabel jLabel11; private javax.swing.JLabel jLabel12; private javax.swing.JLabel jLabel13; private javax.swing.JLabel jLabel14; private javax.swing.JLabel jLabel15; private javax.swing.JLabel jLabel16; private javax.swing.JLabel jLabel17; private javax.swing.JLabel jLabel18; private javax.swing.JLabel jLabel19; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel20; private javax.swing.JLabel jLabel21; private javax.swing.JLabel jLabel22; private javax.swing.JLabel jLabel23; private javax.swing.JLabel jLabel24; private javax.swing.JLabel jLabel25; private javax.swing.JLabel jLabel26; private javax.swing.JLabel jLabel27; private javax.swing.JLabel jLabel28; private javax.swing.JLabel jLabel29; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel30; private javax.swing.JLabel jLabel31; private javax.swing.JLabel jLabel32; private javax.swing.JLabel jLabel33; private javax.swing.JLabel jLabel34; private javax.swing.JLabel jLabel35; private javax.swing.JLabel jLabel36; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JLabel jLabel7; private javax.swing.JLabel jLabel8; private javax.swing.JLabel jLabel9; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel10; private javax.swing.JPanel jPanel11; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanel4; private javax.swing.JPanel jPanel5; private javax.swing.JPanel jPanel6; private javax.swing.JPanel jPanel7; private javax.swing.JPanel jPanel8; private javax.swing.JPanel jPanel9; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JTabbedPane jTabbedPane1; private javax.swing.JTable listView; private javax.swing.JTextField list_name; private javax.swing.JSpinner maxAttempts; private javax.swing.JSpinner maxRingTime; private javax.swing.JSlider msg_idx; private javax.swing.JRadioButton multi; private javax.swing.JButton next_msg; private javax.swing.JSpinner number_lines; private javax.swing.JButton prev_msg; private javax.swing.JButton reset_list; private javax.swing.JButton save_setup; private javax.swing.JButton select_file; private javax.swing.JComboBox selected_list; private javax.swing.JTextField silence_duration; private javax.swing.JTextField silence_threshold; private javax.swing.JRadioButton single; private javax.swing.JTextField sip_auth; private javax.swing.JTextField sip_end; private javax.swing.JTextField sip_host; private javax.swing.JTextField sip_name; private javax.swing.JPasswordField sip_pass; private javax.swing.JTextField sip_start; private javax.swing.JTextField sip_user; private javax.swing.JButton start; private javax.swing.JTextField start1; private javax.swing.JTextField start2; private javax.swing.JTextField start3; private javax.swing.JTextField start4; private javax.swing.JTextField start5; private javax.swing.JTextField start6; private javax.swing.JTextField start7; private javax.swing.JLabel status; private javax.swing.JRadioButton terminate; private javax.swing.JLabel title; private javax.swing.JCheckBox voicemail_hangup; private javax.swing.JTextField wav_filename; private javax.swing.JRadioButton xfer; private javax.swing.JTextField xfer_digit; private javax.swing.JTextField xfer_number; // End of variables declaration//GEN-END:variables //global data enum states { STOPPED, CALLING, STOPPING}; states state = states.STOPPED; Thread callingThread; int lineCount; SIPClient sip; Lines lines[]; boolean registered; short silence[] = new short[160]; short tmp[] = new short[160]; Wav wav[]; SQL psql; //persistant sql connection String dbname = "broadcast"; String listid; volatile boolean processing = false; int skipCount; int maxquietcount; static String args[]; static class update { public String number, status, survey; public update(String number, String status, String survey) { this.number = number; this.status = status; this.survey = survey; } } Vector<update> updateList = new Vector<update>(); final static int NUMQUESTIONS = 99; //actions final static int A_CONT = 0; final static int A_TERMINATE = 4; final static int A_SINGLE = 1; final static int A_MULTI = 2; final static int A_GOTOUSER = 3; final static int A_GOTOIDX = 5; final static int A_XFER = 6; public void createDatabase() { if (new File(dbPath + "/" + databaseName + "/service.properties").exists()) return; //already exists JFTask task = new JFTask() { public boolean work() { this.setTitle("Creating database..."); this.setLabel("Creating database..."); this.setProgress(25); SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName + ";" + "create=true")) { this.setLabel("Database create failed : SQL connection failed"); return false; } this.setProgress(50); if (!sql.execute("create table lists (id int GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1) primary key, name varchar(37) not null unique)")) { this.setLabel("Database create failed : Create Table failed (already created?)"); return false; } this.setProgress(75); if (!sql.execute("create table listdata (id int not null, number varchar(32) not null, status varchar(32) default 'new' not null, attempts int default 0 not null, survey varchar(64), called timestamp, unique(number, id))")) { this.setLabel("Database create failed : Create Table failed (already created?)"); return false; } this.setProgress(100); this.setLabel("Database created succesfully"); return true; } }; ProgressDialog pd = new ProgressDialog(this, true, task); pd.setVisible(true); } public void setStatus(String str) { status.setText("Status:" + str); } public String safe(String str) { char strin[] = str.toCharArray(); char strout[] = new char[str.length()]; for(int a=0;a<strin.length;a++) { if ((Character.toLowerCase(strin[a]) >= 'a') && (Character.toLowerCase(strin[a]) <= 'z')) { strout[a] = strin[a]; continue; } if ((strin[a] >= '0') && (strin[a] <= '9')) { strout[a] = strin[a]; continue; } strout[a] = '_'; } return new String(strout); } public String sip_pass_getText() { return new String(sip_pass.getPassword()); } public void createList() { String safe = safe(list_name.getText()); if (safe.length() == 0) return; SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); return; } if (!sql.execute("insert into lists values (default, '" + safe + "')")) { setStatus("Insert failed (already created?)"); return; } setStatus("OK:CreateTable:" + safe); updateAvailableLists(); } public void deleteList() { String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; if (JOptionPane.showConfirmDialog(null, "Delete List:" + sel + "?", "Sure?", JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) return; SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); return; } if (!sql.execute("delete from listdata where id=(select id from lists where name='"+sel+"')")) { setStatus("delete from lists failed(1)"); return; } if (!sql.execute("delete from lists where name='"+sel+"'")) { setStatus("delete from lists failed(2)"); return; } setStatus("OK:DeleteList:"+sel); updateAvailableLists(); updateList(); } public void resetList() { String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; if (JOptionPane.showConfirmDialog(null, "Reset List:" + sel + "?", "Sure?", JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) return; SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); return; } if (!sql.execute("update listdata set status='new', attempts = 0, survey = '', called = null where id=(select id from lists where name='" + sel + "')")) { setStatus("update failed"); return; } setStatus("OK:ResetList:"+sel); updateList(); } public void fixList(boolean quite, boolean errors) { String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; if (!quite) { String msg; if (errors) { msg = "Fix 'errors' in List:" + sel + "?"; } else { msg = "Fix 'calling' in List:" + sel + "?"; } if (JOptionPane.showConfirmDialog(null, msg, "Sure?", JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) return; } SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); return; } String query; if (errors) { query = "update listdata set status='new', attempts = 0, survey = '', called = null where status like 'err_%' and id=(select id from lists where name='" + sel + "')"; } else { query = "update listdata set status='new', attempts = 0, survey = '', called = null where status='calling' and id=(select id from lists where name='" + sel + "')"; } if (!sql.execute(query)) { setStatus("update failed"); return; } if (!quite) { setStatus("OK:FixList:"+sel); } updateList(); } public final void updateAvailableLists() { File file = new File(dbPath + "/" + databaseName); if (!file.exists()) return; //not ready String data[][]; SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { // setStatus("SQL connection failed"); return; } data = sql.select("select name from lists"); if (data == null) { // setStatus("select failed"); return; } int yc = data.length; if (yc == 0) { //??? } ArrayList<String> al = new ArrayList<String>(); String e; for(int y=0;y<yc;y++) { e = data[y][0]; al.add(e); } selected_list.setModel(new DefaultComboBoxModel(al.toArray())); // selectedList.setSelectedIndex(0); updateList(); } private String getid(SQL sql, String sel) { String data[][]; data = sql.select("select id from lists where name='" + sel +"'"); if (data == null) { // setStatus("select failed"); return null; } int yc = data.length; if (yc != 1) return null; return data[0][0]; } public void importList() { String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(JF.getCurrentPath())); if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return; String num; SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); return; } int line = 1; int errcnt = 0; int okcnt = 0; ArrayList<String> numbers = null; int duptag = 1; if (allowdups) { numbers = new ArrayList<String>(); int cnt = listView.getRowCount(); for(int a=0;a<cnt;a++) { numbers.add((String)listView.getValueAt(a, 0)); } } try { String id = getid(sql, sel); if (id == null) throw new Exception("unable to find list"); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(chooser.getSelectedFile().toString()))); do { num = reader.readLine(); if (num == null) break; int idx2 = num.indexOf(","); if (idx2 != -1) { num = num.substring(0, idx2); } num = num.trim(); if (allowdups) { //check if this number already exists and add a tag to it if (numbers.contains(num)) { num += "," + duptag++; } numbers.add(num); } if (!sql.execute("insert into listdata (id, number) values (" + id + ",'" + num + "')")) { errcnt++; } else { okcnt++; } line++; } while (true); reader.close(); } catch (Exception e) { setStatus(e.toString()); updateList(); return; } setStatus("OK : File loaded : Inserted = " + okcnt + " : Errors = " + errcnt); updateList(); } public void exportList() { String data[][]; String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(JF.getCurrentPath())); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return; String num; SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); return; } data = sql.select("select number,status,attempts,survey,called from listdata where id=(select id from lists where name='" + sel + "')"); if (data == null) { setStatus("select failed (1)"); return; } try { FileOutputStream fos = new FileOutputStream(chooser.getSelectedFile().toString()); for(int a=0;a<data.length;a++) { String timestamp = data[a][4]; String date = "null", time = "null"; if (timestamp != null && timestamp.length() > 10) { date = timestamp.substring(0, 10); time = timestamp.substring(11); } fos.write((data[a][0] + "," + data[a][1] + "," + data[a][2] + "," + data[a][3] + "," + date + "," + time + "\r\n").getBytes()); } fos.close(); } catch (Exception e) { setStatus(e.toString()); return; } setStatus("OK : List exported"); } private String cols[] = new String[] {"Number","Status","Attempts","Survey","Timestamp"}; public void updateList() { String data[][]; String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) { listView.setModel(new DefaultTableModel(new String[][] {}, cols)); return; } SQL sql = new SQL(); if (!sql.connect("jdbc:derby:" + databaseName)) { // setStatus("SQL connection failed"); return; } data = sql.select("select number, status, attempts, survey, called from listdata where id=(select id from lists where name='" + sel + "')"); if (data == null) { data = new String[][] {}; } listView.setModel(new DefaultTableModel(data, cols)); } public boolean isConfigValid() { if (xfer_digit.getText().length() != 1) {setStatus("Error:Transfer digit is invalid"); return false;} for(int a=0;a<NUMQUESTIONS;a++) { if (questions.action[a] == A_GOTOUSER) { for(int b=0;b<9;b++) { if (questions.gotouser[a][b] != 0) break; if (b==8) { setStatus("Error:Question #" + (a+1) + " has an undefined goto action."); return false; } } } if (questions.action[a] == A_GOTOIDX) { if (questions.gotoidx[a] == 0) { setStatus("Error:Question #" + (a+1) + " has an undefined goto action."); return false; } } } if (sip_host.getText().length() == 0) { setStatus("Error:SIP host undefined."); return false; } if (sip_user.getText().length() == 0) { setStatus("Error:SIP user undefined."); return false; } int cnt = 0; try { int start = Integer.valueOf(sip_start.getText()); if (start < 1024 || start > 60000) { setStatus("Error:SIP Port start is not in range"); return false; } int end = Integer.valueOf(sip_end.getText()); if (end < 1024 || end > 60000) { setStatus("Error:SIP Port end is not in range"); return false; } if (end < start || (end-start < 1000)) { setStatus("Error:SIP Port range is invalid"); return false; } for(int a=0;a<NUMQUESTIONS;a++) { if (!questions.enabled[a]) continue; File test = new File(questions.wav[a]); if (!test.exists()) { setStatus("Error : Message #" + (a+1) + " WAV file doesn't exist."); return false; } cnt++; } } catch (Exception e) { setStatus("Error:" + e); return false; } if (cnt == 0) { setStatus("Error:No messages defined."); return false; } cnt = 0; if (enable_g729a.isSelected()) cnt++; if (enable_g711u.isSelected()) cnt++; if (enable_g711a.isSelected()) cnt++; if (cnt == 0) { setStatus("Error:Must enable at least one codec"); return false; } return true; } public static class Settings implements Serializable { static final long serialVersionUID = 1000L; String sql_host, sql_user, sql_pass; //obsolete (do not delete or old cfg will not load) String sip_name, sip_user, sip_auth, sip_host, sip_pass; String wav_filename; //obsolete int numberLines = 8; String xfer; boolean disable_g729a; //obsolete int delay = 100; boolean enable_xfer = false; char xfer_digit = '0'; int maxRingTime = 60; //in seconds int maxAttempts = 3; boolean disable_detect = false; boolean enable_g729a = true, enable_g711u = true, enable_g711a = false; boolean enable_reinvites = true; boolean check_update = true; int greetingThreshold = 1000, silenceThreshold = 1000, silenceDuration = 1000; //calling times boolean day[] = new boolean[] {false, true, true, true, true, true, false}; String start[] = new String[] {"10:00", "10:00", "10:00", "10:00", "10:00", "10:00", "10:00"}; String end[] = new String[] {"17:00", "17:00", "17:00", "17:00", "17:00", "17:00", "17:00"}; //sip port range int sip_start, sip_end; boolean voicemail_hangup; boolean exit_on_close_window; } private Settings settings; public final void loadSetup() { try { FileInputStream fis = new FileInputStream(JF.getUserPath() + "/broadcast" + cfgSuffix + ".cfg"); ObjectInputStream ois = new ObjectInputStream(fis); settings = (Settings)ois.readObject(); fis.close(); sip_name.setText(settings.sip_name); sip_user.setText(settings.sip_user); sip_auth.setText(settings.sip_auth); sip_host.setText(settings.sip_host); sip_pass.setText(settings.sip_pass); if (settings.sip_start == 0) { settings.sip_start = 6000; settings.sip_end = 9000; } sip_start.setText("" + settings.sip_start); sip_end.setText("" + settings.sip_end); number_lines.setValue(new Integer(settings.numberLines)); xfer_number.setText(settings.xfer); if (settings.delay == 0) settings.delay = 100; delay.setValue(new Integer(settings.delay)); enable_xfer.setSelected(settings.enable_xfer); xfer_digit.setText("" + settings.xfer_digit); if (settings.maxRingTime == 0) settings.maxRingTime = 60; maxRingTime.setValue(new Integer(settings.maxRingTime)); if (settings.maxAttempts == 0) settings.maxAttempts = 3; maxAttempts.setValue(new Integer(settings.maxAttempts)); enable_g729a.setSelected(settings.enable_g729a); enable_g711u.setSelected(settings.enable_g711u); enable_g711a.setSelected(settings.enable_g711a); enable_reinvites.setSelected(settings.enable_reinvites); check_update.setSelected(settings.check_update); exit_on_close_window.setSelected(settings.exit_on_close_window); human_vm_detect.setSelected(!settings.disable_detect); greeting_threshold.setText(Integer.toString(settings.greetingThreshold)); silence_threshold.setText(Integer.toString(settings.silenceThreshold)); silence_duration.setText(Integer.toString(settings.silenceDuration)); voicemail_hangup.setSelected(settings.voicemail_hangup); if (settings.day == null) { settings.day = new boolean[] {false, true, true, true, true, true, false}; } day1.setSelected(settings.day[0]); day2.setSelected(settings.day[1]); day3.setSelected(settings.day[2]); day4.setSelected(settings.day[3]); day5.setSelected(settings.day[4]); day6.setSelected(settings.day[5]); day7.setSelected(settings.day[6]); if (settings.start == null) { settings.start = new String[] {"10:00", "10:00", "10:00", "10:00", "10:00", "10:00", "10:00"}; } start1.setText(settings.start[0]); start2.setText(settings.start[1]); start3.setText(settings.start[2]); start4.setText(settings.start[3]); start5.setText(settings.start[4]); start6.setText(settings.start[5]); start7.setText(settings.start[6]); if (settings.end == null) { settings.end = new String[] {"17:00", "17:00", "17:00", "17:00", "17:00", "17:00", "17:00"}; } end1.setText(settings.end[0]); end2.setText(settings.end[1]); end3.setText(settings.end[2]); end4.setText(settings.end[3]); end5.setText(settings.end[4]); end6.setText(settings.end[5]); end7.setText(settings.end[6]); fis = new FileInputStream(JF.getUserPath() + "/broadcast-msgs" + cfgSuffix + ".cfg"); ois = new ObjectInputStream(fis); questions = (Questions)ois.readObject(); fis.close(); } catch (FileNotFoundException e) { loadDefaults(); setStatus("Loading default settings"); JFLog.log("No config found"); } catch (Exception e) { loadDefaults(); setStatus("Load Settings Failed:" + e); JFLog.log(e); } validateOptions(); } private void loadDefaults() { settings = new Settings(); sip_start.setText("6000"); sip_end.setText("9000"); number_lines.setValue(new Integer(8)); delay.setValue(new Integer(100)); maxRingTime.setValue(new Integer(60)); maxAttempts.setValue(new Integer(3)); human_vm_detect.setSelected(true); greeting_threshold.setText("1000"); silence_threshold.setText("1000"); silence_duration.setText("2000"); voicemail_hangup.setSelected(false); enable_reinvites.setSelected(true); enable_g729a.setSelected(true); enable_g711u.setSelected(true); enable_g711a.setSelected(false); check_update.setSelected(true); exit_on_close_window.setSelected(false); day1.setSelected(false); day2.setSelected(true); day3.setSelected(true); day4.setSelected(true); day5.setSelected(true); day6.setSelected(true); day7.setSelected(false); start1.setText("10:00"); start2.setText("10:00"); start3.setText("10:00"); start4.setText("10:00"); start5.setText("10:00"); start6.setText("10:00"); start7.setText("10:00"); end1.setText("17:00"); end2.setText("17:00"); end3.setText("17:00"); end4.setText("17:00"); end5.setText("17:00"); end6.setText("17:00"); end7.setText("17:00"); } private void validateTime(JTextField field, String def) { String txt = field.getText(); String f[] = txt.split("[:]"); if (f.length != 2) { field.setText(def); return; } int hr = JF.atoi(f[0]); int min = JF.atoi(f[1]); if (hr < 0 || hr > 24 || min < 0 || min > 59) { field.setText(def); } } private void validateOptions() { if ((Integer)number_lines.getValue() < 1) { number_lines.setValue(new Integer(1)); } if ((Integer)delay.getValue() < 100) { delay.setValue(new Integer(100)); } if ((Integer)delay.getValue() > 10000) { delay.setValue(new Integer(10000)); } if ((Integer)maxRingTime.getValue() < 10) { maxRingTime.setValue(new Integer(10)); } if ((Integer)maxRingTime.getValue() > 100) { maxRingTime.setValue(new Integer(100)); } if ((Integer)maxAttempts.getValue() < 1) { maxAttempts.setValue(new Integer(1)); } if ((Integer)maxAttempts.getValue() > 100) { maxAttempts.setValue(new Integer(100)); } validateTime(start1, "10:00"); validateTime(start2, "10:00"); validateTime(start3, "10:00"); validateTime(start4, "10:00"); validateTime(start5, "10:00"); validateTime(start6, "10:00"); validateTime(start7, "10:00"); validateTime(end1, "17:00"); validateTime(end2, "17:00"); validateTime(end3, "17:00"); validateTime(end4, "17:00"); validateTime(end5, "17:00"); validateTime(end6, "17:00"); validateTime(end7, "17:00"); int value = JF.atoi(greeting_threshold.getText()); if (value < 100 || value > 32000) greeting_threshold.setText("1000"); value = JF.atoi(silence_threshold.getText()); if (value < 100 || value > 32000) silence_threshold.setText("1000"); value = JF.atoi(silence_duration.getText()); if (value < 100 || value > 5000) silence_duration.setText("2000"); } public void saveSetup() { validateOptions(); saveQuestion(); try { FileOutputStream fos = new FileOutputStream(JF.getUserPath() + "/broadcast" + cfgSuffix + ".cfg"); ObjectOutputStream oos = new ObjectOutputStream(fos); settings = new Settings(); settings.sip_name = sip_name.getText(); settings.sip_user = sip_user.getText(); settings.sip_auth = sip_auth.getText(); settings.sip_host = sip_host.getText(); settings.sip_pass = sip_pass_getText(); settings.sip_start = Integer.valueOf(sip_start.getText()); settings.sip_end = Integer.valueOf(sip_end.getText()); settings.wav_filename = ""; //obsolete settings.numberLines = (Integer)(number_lines.getValue()); settings.xfer = xfer_number.getText(); settings.disable_detect = !human_vm_detect.isSelected(); settings.greetingThreshold = JF.atoi(greeting_threshold.getText()); settings.silenceThreshold = JF.atoi(silence_threshold.getText()); settings.silenceDuration = JF.atoi(silence_duration.getText()); settings.voicemail_hangup = voicemail_hangup.isSelected(); settings.delay = (Integer)(delay.getValue()); settings.enable_xfer = enable_xfer.isSelected(); settings.xfer_digit = xfer_digit.getText().charAt(0); settings.maxRingTime = (Integer)(maxRingTime.getValue()); settings.maxAttempts = (Integer)(maxAttempts.getValue()); settings.enable_g729a = enable_g729a.isSelected(); settings.enable_g711u = enable_g711u.isSelected(); settings.enable_g711a = enable_g711a.isSelected(); settings.enable_reinvites = enable_reinvites.isSelected(); settings.check_update = check_update.isSelected(); settings.day[0] = day1.isSelected(); settings.day[1] = day2.isSelected(); settings.day[2] = day3.isSelected(); settings.day[3] = day4.isSelected(); settings.day[4] = day5.isSelected(); settings.day[5] = day6.isSelected(); settings.day[6] = day7.isSelected(); settings.start[0] = start1.getText(); settings.start[1] = start2.getText(); settings.start[2] = start3.getText(); settings.start[3] = start4.getText(); settings.start[4] = start5.getText(); settings.start[5] = start6.getText(); settings.start[6] = start7.getText(); settings.end[0] = end1.getText(); settings.end[1] = end2.getText(); settings.end[2] = end3.getText(); settings.end[3] = end4.getText(); settings.end[4] = end5.getText(); settings.end[5] = end6.getText(); settings.end[6] = end7.getText(); oos.writeObject(settings); fos.close(); fos = new FileOutputStream(JF.getUserPath() + "/broadcast-msgs" + cfgSuffix + ".cfg"); oos = new ObjectOutputStream(fos); oos.writeObject(questions); fos.close(); } catch (Exception e) { setStatus("Save Settings Failed:" + e); JFLog.log(e); return; } setStatus("OK : saved"); } public int firstlocalsipport = 6000; public int nextlocalsipport = 6000; public int lastlocalsipport = 9000; public int getlocalsipport() { int ret = nextlocalsipport; nextlocalsipport++; if (nextlocalsipport == lastlocalsipport) nextlocalsipport = firstlocalsipport; return ret; } public String getHost(String host) { int idx = host.indexOf(":"); if (idx == -1) return host; return host.substring(0, idx); } public int getPort(String host, int def) { int idx = host.indexOf(":"); if (idx == -1) return def; return Integer.valueOf(host.substring(idx+1)); } public static class Lines { boolean inuse = false; //this line in use? boolean ringing = false; //is line ringing boolean talking = false; //are we talking to someone on a line boolean xfered = false; //was call transfered boolean hello = false; //did we hear something on the line boolean repeat = false; //repeating message String number; //number we called String callid; //not caller id, but a unique ID for this call leg String survey; //user responses (long responses are in brackets) String multi; //for long inputs RTP rtp; int msgidx = 0; int wavpos = 0; int ringwait = 0; int postwait = 0; int quietcount = 0; //wait till we hear quiet after hello (answering machine detection) int noresponse = 0; boolean voicemail = false; } public void startCalling() { if (!isConfigValid()) return; String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) { setStatus("Pick a valid list(1)"); return; } saveSetup(); firstlocalsipport = settings.sip_start; nextlocalsipport = firstlocalsipport; lastlocalsipport = settings.sip_end; skipCount = 0; maxquietcount = settings.silenceDuration / 20; //lock resources setState(false); if (sip_pass_getText().length() == 0) setStatus("waiting for register"); else setStatus("calling"); JFLog.log("thresholds : " + settings.greetingThreshold + "," + settings.silenceThreshold + "," + settings.silenceDuration); fixList(true, false); //load WAV file(s) wav = new Wav[NUMQUESTIONS]; int cnt = 0; for(int a=0;a<NUMQUESTIONS;a++) { wav[a] = new Wav(); if (!questions.enabled[a]) continue; if (!wav[a].load(questions.wav[a])) { setStatus(wav[a].errmsg); setState(true); return; } cnt++; } if (cnt == 0) { setStatus("no messages"); setState(true); return; } //create persistant sql connection psql = new SQL(); if (!psql.connect("jdbc:derby:" + databaseName)) { setStatus("SQL connection failed"); setState(true); return; } listid = getid(psql, sel); if (listid == null) { setStatus("Error : Pick a valid list"); psql.close(); setState(true); return; } state = states.CALLING; start.setText("Stop"); //create SIP resources lineCount = (Integer)number_lines.getValue(); sip = new SIPClient(); int fail = 0; while (!sip.init(getHost(sip_host.getText()), getPort(sip_host.getText(), 5060), getlocalsipport(), this, SIP.Transport.UDP)) { fail++; if (fail == 10) { setStatus("Error:SIP init failed"); setState(true); state = states.STOPPED; start.setText("Start!"); return; } } if (sip_pass_getText().length() > 0) { sip.register(sip_name.getText(), sip_user.getText(), sip_auth.getText(), sip_pass_getText()); registered = false; } else { registered = true; } lines = new Lines[lineCount]; for(int a=0;a<lineCount;a++) { lines[a] = new Lines(); } //create 20ms timer java.util.Timer timer = new java.util.Timer(); timer.scheduleAtFixedRate(new TimerTask() { public void run() { process(); } }, 0, 20); int delayms = (Integer)delay.getValue(); while (state == states.CALLING) { //look for a free SIP resource and fill it with a call JF.sleep(delayms); processUpdateList(); if (!inCallingTime()) { JF.sleep(250); continue; } String number = nextAvailableNumber(); //NOTE:this keeps sql connection established (keep alive) if (!registered) continue; if (number == null) { //no more numbers to dial if (anyStillCalling()) continue; setStatus("Finished list"); break; } for(int a=0;a<lineCount;a++) { if (lines[a].inuse) continue; lines[a].rtp = null; lines[a].msgidx = 0; lines[a].wavpos = 0; lines[a].ringwait = 0; lines[a].postwait = 0; lines[a].xfered = false; lines[a].hello = false; lines[a].repeat = false; lines[a].number = number; lines[a].quietcount = 0; lines[a].voicemail = false; lines[a].survey = ""; lines[a].multi = ""; lines[a].inuse = true; lines[a].callid = dialNumber(number, lines[a]); markCalling(number); break; } } while (anyStillCalling()) { processUpdateList(); JF.sleep(1000); //wait for all calls to finish } processUpdateList(); psql.close(); timer.cancel(); //unlock resources setState(true); if (state == states.STOPPING) { setStatus("stopped"); } sip.unregister(); sip.uninit(); state = states.STOPPED; start.setText("Start!"); } public void stopCalling() { state = states.STOPPING; setStatus("stopping"); } public void forceStopCalling() { setStatus("killing connections"); for(int a=0;a<lines.length;a++) { if (lines[a].inuse) { sip.bye(lines[a].callid); endCall(lines[a], "err_force_stop"); } } } public boolean inCallingTime() { Calendar c = Calendar.getInstance(); int cday = c.get(Calendar.DAY_OF_WEEK); //1-7 cday--; //0-6 int chr = c.get(Calendar.HOUR_OF_DAY); //0-23 int cmin = c.get(Calendar.MINUTE); //0-59 if (!settings.day[cday]) return false; String start = settings.start[cday]; String startf[] = start.split("[:]"); int starthr = JF.atoi(startf[0]); int startmin = JF.atoi(startf[1]); if (chr < starthr) return false; if (chr == starthr && cmin < startmin) return false; String end = settings.end[cday]; String endf[] = end.split("[:]"); int endhr = JF.atoi(endf[0]); int endmin = JF.atoi(endf[1]); if (chr > endhr) return false; if (chr == endhr && cmin > endmin) return false; return true; } public void setState(boolean state) { sip_host.setEnabled(state); sip_auth.setEnabled(state); sip_name.setEnabled(state); sip_user.setEnabled(state); sip_pass.setEnabled(state); sip_start.setEnabled(state); sip_end.setEnabled(state); save_setup.setEnabled(state); create_list.setEnabled(state); delete_list.setEnabled(state); selected_list.setEnabled(state); import_list.setEnabled(state); number_lines.setEnabled(state); xfer_number.setEnabled(state); reset_list.setEnabled(state); list_name.setEnabled(state); enable_g729a.setEnabled(state); enable_g711u.setEnabled(state); enable_g711a.setEnabled(state); enable_reinvites.setEnabled(state); check_update.setEnabled(state); exit_on_close_window.setEnabled(state); human_vm_detect.setEnabled(state); greeting_threshold.setEnabled(state); silence_threshold.setEnabled(state); silence_duration.setEnabled(state); voicemail_hangup.setEnabled(state); export_list.setEnabled(state); delay.setEnabled(state); enable_xfer.setEnabled(state); xfer_digit.setEnabled(state); fix_list.setEnabled(state); enable.setEnabled(state); wav_filename.setEnabled(state); select_file.setEnabled(state); single.setEnabled(state); multi.setEnabled(state); count.setEnabled(state); cont.setEnabled(state); terminate.setEnabled(state); gotouser.setEnabled(state); gotoidx.setEnabled(state); gotoidxnum.setEnabled(state); goto_1.setEnabled(state); goto_2.setEnabled(state); goto_3.setEnabled(state); goto_4.setEnabled(state); goto_5.setEnabled(state); goto_6.setEnabled(state); goto_7.setEnabled(state); goto_8.setEnabled(state); goto_9.setEnabled(state); maxRingTime.setEnabled(state); maxAttempts.setEnabled(state); xfer.setEnabled(state); day1.setEnabled(state); day2.setEnabled(state); day3.setEnabled(state); day4.setEnabled(state); day5.setEnabled(state); day6.setEnabled(state); day7.setEnabled(state); start1.setEnabled(state); start2.setEnabled(state); start3.setEnabled(state); start4.setEnabled(state); start5.setEnabled(state); start6.setEnabled(state); start7.setEnabled(state); end1.setEnabled(state); end2.setEnabled(state); end3.setEnabled(state); end4.setEnabled(state); end5.setEnabled(state); end6.setEnabled(state); end7.setEnabled(state); } public String nextAvailableNumber() { String data[][]; String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return null; //select next available number where status='new' or 'busy'. order by status desc to get 'new' before 'busy' data = psql.select("select number from listdata where (status = 'new' or status = 'busy') and attempts < " + settings.maxAttempts + " and id=" + listid + " order by status desc, attempts asc fetch first row only"); if (data == null) { setStatus("nextAvailableNumber : select failed (1)"); return null; } if (data.length == 0) return null; return data[0][0]; } public Codec[] getCodecs() { Codec codecs[] = new Codec[0]; if (enable_g729a.isSelected()) codecs = SIP.addCodec(codecs, RTP.CODEC_G729a); if (enable_g711u.isSelected()) codecs = SIP.addCodec(codecs, RTP.CODEC_G711u); if (enable_g711a.isSelected()) codecs = SIP.addCodec(codecs, RTP.CODEC_G711a); return codecs; } public String dialNumber(String number, Lines line) { //generate a callid and initiate a sip call line.rtp = new RTP(); line.rtp.init(this); SDP sdp = new SDP(); SDP.Stream astream = sdp.addStream(SDP.Type.audio); astream.port = line.rtp.getlocalrtpport(); astream.codecs = getCodecs(); // if (allowdups) { int idx = number.indexOf(","); if (idx != -1) { number = number.substring(0, idx); } // } return sip.invite(number, sdp); } public void markCalling(String number) { String data[][]; //set status='calling' and increment attempts String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; int attempts = 0; data = psql.select("select attempts from listdata where number = '" + number + "' and id=" + listid); if (data == null) { setStatus("select failed"); return; } if (data.length == 0) return; attempts = Integer.valueOf(data[0][0]) + 1; if (!psql.execute("update listdata set attempts = " + attempts + ", status = 'calling' where number = '" + number + "' and id=" + listid)) { setStatus("update failed"); return; } //update local copy int rc = listView.getRowCount(); for(int row=0;row<rc;row++) { if (((String)listView.getValueAt(row, 0)).equals(number)) { listView.setValueAt("calling", row, 1); listView.setValueAt(new Integer(attempts), row, 2); listView.repaint(); return; } } } public void unmarkCalling() { String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; if (!psql.execute("update lists set status = 'aborted', called = current_timestamp where status = 'calling' and id=" + listid)) { setStatus("update failed"); return; } updateList(); } public boolean anyStillCalling() { String data[][]; String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return false; data = psql.select("select count(number) from listdata where status = 'calling' and id=" + listid); if (data == null) { setStatus("select failed"); return false; } if (data.length == 0) return false; return !(data[0][0].equals("0")); } public void endCall(Lines line, String status) { System.out.println("endCall:" + line.number + ":status=" + status); line.talking = false; line.rtp.stop(); line.rtp.uninit(); line.rtp = null; line.callid = null; line.noresponse = 0; line.inuse = false; updateList.add(new update(line.number, status, line.survey)); } public void processUpdateList() { String sel = (String)selected_list.getSelectedItem(); if (sel == null || sel.length() == 0) return; update u; while (updateList.size() > 0) { u = updateList.remove(0); if (!psql.execute("update listdata set status = '" + u.status + "', survey = '" + u.survey + "', called = current_timestamp where number = '" + u.number + "' and id=" + listid)) { setStatus("endCall : update failed : " + u.number); return; } String called = psql.select1value("select called from listdata where number = '" + u.number + "' and id=" + listid); //update local copy int rc = listView.getRowCount(); for(int row=0;row<rc;row++) { if (((String)listView.getValueAt(row, 0)).equals(u.number)) { listView.setValueAt(u.status, row, 1); listView.setValueAt(u.survey, row, 3); listView.setValueAt(called, row, 4); listView.repaint(); break; } } } } public void process() { //20ms audio timer byte encoded[]; if (processing) { skipCount++; setStatus("audio timer skipped : system too slow : reduce # of lines : skipCount=" + skipCount); return; } processing = true; try { for(int a=0;a<lineCount;a++) { if (!lines[a].inuse) continue; if (!lines[a].talking) { lines[a].ringwait++; if (lines[a].ringwait == 50 * settings.maxRingTime) { //there are 50 process() per second //waiting/ringing for too long (1min) sip.cancel(lines[a].callid); endCall(lines[a], "no_anwser"); } continue; } if (lines[a].quietcount < maxquietcount) { if (!lines[a].hello) { //detect hello/answering machine if (lines[a].rtp.getDefaultChannel().getSamples(tmp)) { for(int p=0;p<160;p++) { if (Math.abs(tmp[p]) > settings.greetingThreshold) { lines[a].hello = true; break; } } } } else { //detect end of hello/answering machine beep if (lines[a].rtp.getDefaultChannel().getSamples(tmp)) { int avg = 0; int peek = 0; int val; for(int p=0;p<160;p++) { val = Math.abs(tmp[p]); avg += val; if (val > peek) peek = val; } avg /= 160; if (avg > settings.silenceThreshold) { lines[a].quietcount = 0; if (lines[a].voicemail) continue; if (isVoiceMailBeep(tmp, peek)) { if (settings.voicemail_hangup) { JFLog.log("voicemail detected (hangup) : " + lines[a].number); sip.bye(lines[a].callid); endCall(lines[a], "voicemail"); continue; } else { lines[a].voicemail = true; } } } else { if (lines[a].voicemail) { //silence after voicemail beep detected JFLog.log("voicemail detected : " + lines[a].number); lines[a].quietcount = maxquietcount; } else { lines[a].quietcount++; } } } else { lines[a].quietcount++; //g729a silence suppression (evil) } } encoded = lines[a].rtp.getDefaultChannel().coder.encode(silence); lines[a].rtp.getDefaultChannel().writeRTP(encoded, 0, encoded.length); } else { if (lines[a].wavpos >= wav[lines[a].msgidx].samples.length) { if (questions.action[lines[a].msgidx] == A_CONT) { nextMessage(lines[a]); continue; } if (questions.action[lines[a].msgidx] == A_GOTOIDX) { lines[a].msgidx = questions.gotoidx[lines[a].msgidx] - 1 - 1; nextMessage(lines[a]); continue; } if (questions.action[lines[a].msgidx] == A_XFER) { if (lines[a].xfered) continue; //already tried to xfer call if (xfer_number.getText().length() == 0) continue; //no # to transfer to sip.refer(lines[a].callid, xfer_number.getText()); lines[a].xfered = true; continue; } lines[a].postwait += 160; if (lines[a].postwait == 40000) { //5 seconds if ((questions.action[lines[a].msgidx] == A_TERMINATE) || (questions.action[lines[a].msgidx] == A_XFER) || (lines[a].noresponse == 5)) { sip.bye(lines[a].callid); endCall(lines[a], "ok"); continue; } else { if (questions.action[lines[a].msgidx] == A_MULTI) { if (lines[a].multi.length() > 0) { lines[a].survey += "(" + lines[a].multi + ")"; nextMessage(lines[a]); } else { //repeat message lines[a].repeat = true; //allow immediate response lines[a].wavpos = 0; lines[a].postwait = 0; lines[a].multi = ""; lines[a].noresponse++; } } else if (questions.action[lines[a].msgidx] == A_GOTOUSER) { //repeat message lines[a].repeat = true; //allow immediate response lines[a].wavpos = 0; lines[a].postwait = 0; lines[a].noresponse++; } } } encoded = lines[a].rtp.getDefaultChannel().coder.encode(silence); lines[a].rtp.getDefaultChannel().writeRTP(encoded, 0, encoded.length); } else { encoded = lines[a].rtp.getDefaultChannel().coder.encode(Arrays.copyOfRange(wav[lines[a].msgidx].samples, lines[a].wavpos, lines[a].wavpos + 160)); lines[a].rtp.getDefaultChannel().writeRTP(encoded, 0, encoded.length); lines[a].wavpos += 160; } } } } catch (Exception e) { JFLog.log("process() exception:"); JFLog.log(e); } processing = false; } public void checkVersion() { try { BufferedReader reader = new BufferedReader(new InputStreamReader( new URL("http://jfbroadcast.sourceforge.net/version.php").openStream())); String line = reader.readLine(); if (line.equals(version)) {JFLog.log("version is up-to-date"); return;} JFLog.log("newer version is available : " + line); JOptionPane.showMessageDialog(this, "A newer version of jfbroadcast is available! (v" + line + ")\r\nPlease goto http://jfbroadcast.sourceforge.net to download it", "Info", JOptionPane.INFORMATION_MESSAGE); } catch (Exception e) { JFLog.log("error while checking for version update"); JFLog.log(e); } } //SIPClientInterface public void onRegister(SIPClient sip, boolean status) { if (status) { if (state != states.CALLING) return; registered = true; setStatus("calling"); } else { if (state != states.CALLING) return; setStatus("Error : register failed"); } } public void onTrying(SIPClient sip, String callid) { if (state == states.STOPPED) return; for(int a=0;a<lineCount;a++) { if (!lines[a].inuse) continue; if (!lines[a].callid.equals(callid)) continue; JFLog.log("trying : " + lines[a].number); } } public void onRinging(SIPClient sip, String callid) { if (state == states.STOPPED) return; for(int a=0;a<lineCount;a++) { if (!lines[a].inuse) continue; if (!lines[a].callid.equals(callid)) continue; lines[a].ringing = true; JFLog.log("ringing : " + lines[a].number); } } public void onSuccess(SIPClient sip, String callid, SDP sdp, boolean complete) { if (!complete) return; //not interested in 183 (ringback) if (state == states.STOPPED) return; SDP.Stream astream = sdp.getFirstAudioStream(); if (astream == null) return; for(int a=0;a<lineCount;a++) { if (!lines[a].inuse) continue; if (!lines[a].callid.equals(callid)) continue; if (!lines[a].talking) { int cnt = 0; if (astream.hasCodec(RTP.CODEC_G729a)) cnt++; if (astream.hasCodec(RTP.CODEC_G711u)) cnt++; if (astream.hasCodec(RTP.CODEC_G711a)) cnt++; if ((cnt > 1) && (enable_reinvites.isSelected())) { Codec codecs[] = new Codec[0]; //try to reinvite with one codec if (astream.hasCodec(RTP.CODEC_G729a)) { codecs = new Codec[] {RTP.CODEC_G729a}; } else if (SIP.hasCodec(codecs, RTP.CODEC_G711u)) { codecs = new Codec[] {RTP.CODEC_G711u}; } else if (SIP.hasCodec(codecs, RTP.CODEC_G711a)) { codecs = new Codec[] {RTP.CODEC_G711a}; } SDP localsdp = new SDP(); SDP.Stream localStream = localsdp.addStream(SDP.Type.audio); localStream.codecs = codecs; localStream.port = lines[a].rtp.getlocalrtpport(); JFLog.log("reinvite:" + lines[a].number); sip.reinvite(callid, localsdp); return; } JFLog.log("connected : number=" + lines[a].number); lines[a].rtp.start(); RTPChannel channel = lines[a].rtp.createChannel(astream); if (channel == null) { JFLog.log("Failed to create RTPChannel:" + lines[a].number); return; }; channel.start(); lines[a].ringing = false; if (settings.disable_detect) { lines[a].hello = true; lines[a].quietcount = maxquietcount; } lines[a].talking = true; return; } } } public void onBye(SIPClient sip, String callid) { if (state == states.STOPPED) return; for(int a=0;a<lineCount;a++ ){ if (!lines[a].inuse) continue; if (lines[a].callid.equals(callid)) { endCall(lines[a], "ok"); } } } public int onInvite(SIPClient sip, String callid, String fromid, String fromnumber, SDP sdp) { return 486; //busy } public void onCancel(SIPClient sip, String callid, int code) { if (state == states.STOPPED) return; for(int a=0;a<lineCount;a++ ){ if (!lines[a].inuse) continue; if (lines[a].callid.equals(callid)) { switch (code) { case 486: endCall(lines[a], "busy"); break; default: endCall(lines[a], "err_" + code); break; } } } } public void onRefer(SIPClient sip, String callid) { if (state == states.STOPPED) return; for(int a=0;a<lineCount;a++ ){ if (!lines[a].inuse) continue; if (lines[a].callid.equals(callid)) { endCall(lines[a], "ok_xfered"); } } } public void onNotify(SIPClient sip, String callid, String event, String content) { } public void onAck(SIPClient sip, String callid, SDP sdp) { } //RTPInterface public void rtpSamples(RTPChannel rtp) {} public void rtpDigit(RTPChannel channel, char c) { if (state == states.STOPPED) return; if (c == '*') return; for(int a=0;a<lineCount;a++ ){ if (!lines[a].inuse) continue; if (lines[a].rtp == channel.rtp) { lines[a].noresponse = 0; if ((enable_xfer.isSelected()) && (c == xfer_digit.getText().charAt(0))) { if (lines[a].xfered) return; //already tried to xfer call if (xfer_number.getText().length() == 0) return; sip.refer(lines[a].callid, xfer_number.getText()); lines[a].xfered = true; return; } if ((lines[a].wavpos < 8000 * 5) && (!lines[a].repeat)) { return; //too soon (msg must play at least 5 sec before response is allowed) } switch (questions.action[lines[a].msgidx]) { case A_TERMINATE: break; case A_SINGLE: lines[a].survey += c; nextMessage(lines[a]); break; case A_MULTI: if (c == '#') { lines[a].survey += "(" + lines[a].multi + ")"; nextMessage(lines[a]); } else { lines[a].multi += c; } lines[a].postwait = 0; break; case A_GOTOUSER: if (c == '#') return; //bad input if (c == '0') return; //bad input int newidx = questions.gotouser[lines[a].msgidx][c - '0' - 1]; if ((newidx < 1) || (newidx > 99)) return; //bad input lines[a].survey += c; //see bug # 2 @ jfbroadcast.sf.net lines[a].msgidx = newidx - 1 - 1; //-1 for zero based, -1 for nextMessage() nextMessage(lines[a]); break; } } } } public void rtpH263(RTPChannel rtp, byte[] bytes, int off, int len) {} public void rtpH263_1998(RTPChannel rtp, byte[] bytes, int off, int len) {} public void rtpH263_2000(RTPChannel rtp, byte[] bytes, int off, int len) {} public void rtpH264(RTPChannel rtp, byte[] bytes, int off, int len) {} public void rtpJPEG(RTPChannel rtp, byte[] bytes, int off, int len) {} public void rtpVP8(RTPChannel rtp, byte[] bytes, int off, int len) {} public void rtpInactive(RTPChannel rtp) {} private void nextMessage(Lines line) { line.wavpos = 0; line.postwait = 0; line.multi = ""; line.repeat = false; while (true) { if (line.msgidx == NUMQUESTIONS-1) { sip.bye(line.callid); endCall(line, "ok"); return; } line.msgidx++; if (line.msgidx < 0) continue; // System.out.println("nextMsg=" + line.msgidx); if (questions.enabled[line.msgidx]) return; } } public void rtpPacket(RTPChannel rtp, byte[] data,int pos,int len) {} public void rtcpPacket(RTPChannel rtp, byte[] data,int pos,int len) {} public static class Questions implements Serializable { static final long serialVersionUID = 1000L; boolean enabled[] = new boolean[NUMQUESTIONS]; String wav[] = new String[NUMQUESTIONS]; int action[] = new int[NUMQUESTIONS]; int count[] = new int[NUMQUESTIONS]; //# digits allowed for single entry int gotouser[][] = new int[NUMQUESTIONS][9]; int gotoidx[] = new int[NUMQUESTIONS]; Questions() { for(int a=0;a<NUMQUESTIONS;a++) { enabled[a] = false; wav[a] = new String(); action[a] = A_CONT; count[a] = 0; } } } public static Questions questions = new Questions(); private int idx = 0; public void selectFile() { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(JF.getCurrentPath())); if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return; wav_filename.setText(chooser.getSelectedFile().toString().replaceAll("\\\\", "/")); } private void prevQuestion() { if (idx == 0) return; saveQuestion(); idx--; loadQuestion(); try { msg_idx.setValue(idx); } catch (Exception e) {System.out.println("" + e);} } private void nextQuestion() { if (idx == NUMQUESTIONS-1) return; saveQuestion(); idx++; loadQuestion(); try { msg_idx.setValue(idx); } catch (Exception e) {System.out.println("" + e);} } private void gotoQuestion(int newidx) { saveQuestion(); idx = newidx; loadQuestion(); } private void loadQuestion() { title.setText("#" + (idx+1) + "/" + NUMQUESTIONS); enable.setSelected(questions.enabled[idx]); wav_filename.setText(questions.wav[idx]); cont.setSelected(questions.action[idx] == A_CONT); single.setSelected(questions.action[idx] == A_SINGLE); multi.setSelected(questions.action[idx] == A_MULTI); terminate.setSelected(questions.action[idx] == A_TERMINATE); gotouser.setSelected(questions.action[idx] == A_GOTOUSER); gotoidx.setSelected(questions.action[idx] == A_GOTOIDX); xfer.setSelected(questions.action[idx] == A_XFER); count.setSelectedIndex(questions.count[idx]); goto_1.setText("" + questions.gotouser[idx][0]); goto_2.setText("" + questions.gotouser[idx][1]); goto_3.setText("" + questions.gotouser[idx][2]); goto_4.setText("" + questions.gotouser[idx][3]); goto_5.setText("" + questions.gotouser[idx][4]); goto_6.setText("" + questions.gotouser[idx][5]); goto_7.setText("" + questions.gotouser[idx][6]); goto_8.setText("" + questions.gotouser[idx][7]); goto_9.setText("" + questions.gotouser[idx][8]); gotoidxnum.setText("" + questions.gotoidx[idx]); } private void saveQuestion() { questions.enabled[idx] = enable.isSelected(); questions.wav[idx] = wav_filename.getText(); if (cont.isSelected()) questions.action[idx] = A_CONT; if (single.isSelected()) questions.action[idx] = A_SINGLE; if (multi.isSelected()) questions.action[idx] = A_MULTI; if (terminate.isSelected()) questions.action[idx] = A_TERMINATE; if (gotouser.isSelected()) questions.action[idx] = A_GOTOUSER; if (gotoidx.isSelected()) questions.action[idx] = A_GOTOIDX; if (xfer.isSelected()) questions.action[idx] = A_XFER; questions.count[idx] = count.getSelectedIndex(); questions.gotouser[idx][0] = Math.min(Math.abs(JF.atoi(goto_1.getText())), 99); questions.gotouser[idx][1] = Math.min(Math.abs(JF.atoi(goto_2.getText())), 99); questions.gotouser[idx][2] = Math.min(Math.abs(JF.atoi(goto_3.getText())), 99); questions.gotouser[idx][3] = Math.min(Math.abs(JF.atoi(goto_4.getText())), 99); questions.gotouser[idx][4] = Math.min(Math.abs(JF.atoi(goto_5.getText())), 99); questions.gotouser[idx][5] = Math.min(Math.abs(JF.atoi(goto_6.getText())), 99); questions.gotouser[idx][6] = Math.min(Math.abs(JF.atoi(goto_7.getText())), 99); questions.gotouser[idx][7] = Math.min(Math.abs(JF.atoi(goto_8.getText())), 99); questions.gotouser[idx][8] = Math.min(Math.abs(JF.atoi(goto_9.getText())), 99); questions.gotoidx[idx] = Math.min(Math.abs(JF.atoi(gotoidxnum.getText())), 99); } private void loadHelp(){ try { InputStream is = getClass().getResourceAsStream("readme.txt"); int len = is.available(); byte txt[] = new byte[len]; is.read(txt); help.setText(new String(txt,0,len)); help.setCaretPosition(0); } catch (Exception e) { } } private void processArgs() { if (args == null || args.length == 0) return; for(int a=0;a<args.length;a++) { if (args[a].equals("-start")) { a++; if (a == args.length) { JFLog.log("Error:Must include list with -start option"); return; } startList = args[a]; } else if (args[a].equals("-dbpath")) { a++; if (a == args.length) { JFLog.log("Error:Must include path with -dbpath option"); return; } dbPath = args[a]; } else if (args[a].equals("-cfgsuffix")) { a++; if (a == args.length) { JFLog.log("Error:Must include string with -cfgsuffix option"); return; } cfgSuffix = args[a]; } else if (args[a].equals("-allowdups")) { allowdups = true; } } } private void setPosition() { Dimension d = getSize(); Rectangle s = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); if ((d.width > s.width) || (d.height > s.height)) { if (d.width > s.width) d.width = s.width; if (d.height > s.height) d.height = s.height; setSize(d); } setLocation(s.width/2 - d.width/2, s.height/2 - d.height/2); } public void actionPerformed(ActionEvent e) { Object o = e.getSource(); if (o == exit) { if (lockFile != null) { lockFile.unlock(); } System.exit(0); } if (o == show) { if (isVisible()) { if ((getExtendedState() & Frame.ICONIFIED) == Frame.ICONIFIED) { setExtendedState(getExtendedState() ^ Frame.ICONIFIED); } requestFocus(); } else { setVisible(true); } } } private void setOptsState() { boolean state = human_vm_detect.isSelected(); greeting_threshold.setEnabled(state); silence_threshold.setEnabled(state); silence_duration.setEnabled(state); voicemail_hangup.setEnabled(state); } //voicemail beep is 0.2 sec @ 987.8 Hz (B5 note) //volume is around 7000 (16bit) private boolean isVoiceMailBeep(short samples[], int peek) { //basically check if wave moves up/down smoothly and maintains a //relative constant volume int dir = 0; //unknown short last = samples[1]; if (peek < 2000) return false; //too quiet if (peek > 30000) return false; //too loud int pmax = peek + 1000; int pmin = peek - 1000; int nmax = -peek + 1000; int nmin = -peek - 1000; if (last > samples[0]) { dir = 1; } else { dir = -1; } int wc = -1; //samples / wave count for(int a=2;a<160;a++) { short now = samples[a]; if (dir == 1) { if (now < last) { //hit a peek if (wc != -1) { if (last < pmin || last > pmax) { // System.out.println("+last <> peek:" + last + "<" + pmin + ">" + pmax); return false; } if (wc < 7 || wc > 9) { // System.out.println("wc=" + wc); return false; } //Hz out of range } wc = 0; //start wave count dir = -1; } } else { if (now > last) { //hit valley if (wc != -1) { if (last < nmin || last > nmax) { // System.out.println("-last <> peek:" + last + "<" + nmin + ">" + nmax + ":wc=" + wc); return false; } } dir = 1; } } if (wc != -1) wc++; last = now; } return true; } public SystemTray tray; public TrayIcon icon; public MenuItem exit, show; }