Model.java
上传用户:liming6160
上传日期:2022-06-07
资源大小:785k
文件大小:14k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  *    Copyright (C) 2001 - 2007 Mobicom-Kavkaz, Inc
  3.  *    MFRadio - stream radio client for Java 2 Micro Edition
  4.  *    
  5.  *    Visit the project page at: http://mfradio.sourceforge.net
  6.  *
  7.  *    This program is free software; you can redistribute it and/or modify
  8.  *    it under the terms of the GNU General Public License as published by
  9.  *    the Free Software Foundation; either version 2 of the License, or
  10.  *    (at your option) any later version.
  11.  *
  12.  *    This program is distributed in the hope that it will be useful,
  13.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *    GNU General Public License for more details.
  16.  *
  17.  *    You should have received a copy of the GNU General Public License
  18.  *    along with this program; if not, write to the Free Software
  19.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *    Java (TM) and all Java (TM)-based marks are a trademark or 
  22.  *    registered trademark of Sun Microsystems, Inc, in the United States 
  23.  *    and other countries.
  24.  */
  25. package ru.mobicomk.mfradio.model;
  26. import java.io.ByteArrayInputStream;
  27. import java.io.ByteArrayOutputStream;
  28. import java.io.DataInputStream;
  29. import java.io.DataOutputStream;
  30. import java.io.IOException;
  31. import java.util.Enumeration;
  32. import java.util.Vector;
  33. import javax.microedition.midlet.MIDlet;
  34. import javax.microedition.rms.RecordEnumeration;
  35. import javax.microedition.rms.RecordStore;
  36. import javax.microedition.rms.RecordStoreException;
  37. import javax.microedition.rms.RecordStoreFullException;
  38. import javax.microedition.rms.RecordStoreNotFoundException;
  39. import ru.mobicomk.mfradio.Constants;
  40. import ru.mobicomk.mfradio.iface.ModelListener;
  41. import ru.mobicomk.mfradio.util.StationInfo;
  42. /**
  43.  * <h2>Application data model class </h2>
  44.  * Model containts station playlist, volume level information 
  45.  * and locale for the Player
  46.  *
  47.  * @author Roman Bondarenko, Alexey Rybalko
  48.  * @see ru.mobicomk.mfradio.controller.UIController
  49.  */
  50. public class Model {
  51.     private static final int SETTING_LOCALE = 1;
  52.     /** Maximal player volume level. */
  53.     public static final int MAX_VOL = 100;
  54.     /** Minimal player volume level. */
  55.     public static final int MIN_VOL = 0;
  56.     private Vector titles_;
  57.     private Vector urls_;
  58.     private int selectedIdx_;
  59.     private int volume_; // 0..100
  60.     private ModelListener listener_;
  61.     private MIDlet midlet_;
  62.     //TODO use hash map for common handling of all other settings: load/save, set/get.
  63.     private String localeName;
  64.     /**
  65.      * Creates a new instance of the Model.
  66.      * @param midlet MIDlet object.
  67.      */
  68.     public Model(MIDlet midlet) {
  69.         midlet_ = midlet;
  70.         volume_ = 50;
  71.         selectedIdx_ = -1;
  72.         listener_ = null;
  73.         titles_ = new Vector();
  74.         urls_ = new Vector();
  75.     }
  76.     /**
  77.      * Set listener for this model object. Only one listener may be joined 
  78.      * for model events. 
  79.      * @param listener New listener object.
  80.      */
  81.     public void setModelListener(ModelListener listener) {
  82.         listener_ = listener;
  83.     }
  84.     /**
  85.      * Load application data from storage (RMS) or application properties 
  86.      * into this model object.
  87.      */
  88.     public void load() {
  89.         String[] storesNames = RecordStore.listRecordStores();
  90.         if (!titles_.isEmpty()) {
  91.             titles_.removeAllElements();
  92.             urls_.removeAllElements();
  93.         }
  94.         if (storesNames == null) {
  95.             loadFromProps();
  96.         } else {
  97.             loadSettings();
  98.             loadPlayList();
  99.         }
  100.         if (titles_.size() > 0) {
  101.             selectedIdx_ = 0;
  102.         }
  103.         firePlaylistChanges();
  104.     }
  105.     /**
  106.      * Save application data from this model object into storage (RMS).
  107.      */
  108.     public void save() {
  109.         storeSettings();
  110.         storePlayList();
  111.     }
  112.     /**
  113.      * Update station information in playlist.
  114.      * @param idx Index of the station in playlist.
  115.      * @param si New station information.
  116.      */
  117.     public void setStationInfo(int idx, StationInfo si) {
  118.         urls_.setElementAt(si.Url, idx);
  119.         titles_.setElementAt(si.Title, idx);
  120.         firePlaylistChanges();
  121.     }
  122.     /**
  123.      * Get station information from playlist by position.
  124.      * @param idx Index of the station in playelist.
  125.      * @return Station information object.
  126.      */
  127.     public StationInfo getStationInfo(int idx) {
  128.         if (idx > -1 && idx < urls_.size()) {
  129.             return new StationInfo((String) urls_.elementAt(idx), (String) titles_.elementAt(idx));
  130.         }
  131.         return null;
  132.     }
  133.     /**
  134.      * Get station information from playlist by URL.
  135.      * @param url URL of a station.
  136.      * @return Station information object.
  137.      */
  138.     public StationInfo getStationInfo(String url) {
  139.         return getStationInfo(urls_.indexOf(url));
  140.     }
  141.     /**
  142.      * Add station at tail of the play list. 
  143.      * This method fire <i>Playlist Changes</i> notification of the 
  144.      * {@link ModelListener} interface.
  145.      * @param si New station information.
  146.      */
  147.     public void addStationInfo(StationInfo si) {
  148.         urls_.addElement(si.Url);
  149.         titles_.addElement(si.Title);
  150.         firePlaylistChanges();
  151.     }
  152.     /**
  153.      * Remove station information from playlist. Find station by position. 
  154.      * This method fire <i>Playlist Changes</i> notification of the 
  155.      * {@link ModelListener} interface.
  156.      * @param idx Index of the station in playlist.
  157.      */
  158.     public void deleteStationInfo(int idx) {
  159.         urls_.removeElementAt(idx);
  160.         titles_.removeElementAt(idx);
  161.         firePlaylistChanges();
  162.     }
  163.     /**
  164.      * Volume level accessor.
  165.      * @return Volume level value.
  166.      */
  167.     public int getVolume() {
  168.         return volume_;
  169.     }
  170.     /**
  171.      * Set new volume level value.
  172.      * @param newVolume New volume level value.
  173.      */
  174.     public void setVolume(int newVolume) {
  175.         volume_ = newVolume;
  176.     }
  177.     /**
  178.      * Selected (current) station position accessor.
  179.      * @return Selected station position.
  180.      */
  181.     public int getSelectedStationIdx() {
  182.         return selectedIdx_;
  183.     }
  184.     /**
  185.      * Select new station in playlist.
  186.      * @param idx New selected station index.
  187.      * @throws java.lang.IndexOutOfBoundsException if given index out of range.
  188.      */
  189.     public void selectStation(int idx) throws IndexOutOfBoundsException {
  190.         if (idx > titles_.size() || idx < -1) {
  191.             throw new IndexOutOfBoundsException();
  192.         }
  193.         selectedIdx_ = idx;
  194.     }
  195.     /**
  196.      * Playlist stations titles accessor.
  197.      * @return Playlist stations titles.
  198.      */
  199.     public Enumeration getStationTitles() {
  200.         return titles_.elements();
  201.     }
  202.     /**
  203.      * Size of the playlist accessor.
  204.      * @return Size of the playlist.
  205.      */
  206.     public int getStationsCount() {
  207.         return titles_.size();
  208.     }
  209.     // Privates ////////////////////////////////////////////////////////////////
  210.     private void firePlaylistChanges() {
  211.         if (listener_ != null) {
  212.             listener_.playlistChanges(titles_.elements(), titles_.size());
  213.         }
  214.     }
  215.     private void loadFromProps() {
  216.         for (int n = 1; n < 100; n++) {
  217.             String url = midlet_.getAppProperty(Constants.APP_RADIO_URL_KEY_PREFIX + n);
  218.             if (url == null || url.length() == 0) {
  219.                 break;
  220.             }
  221.             String title = midlet_.getAppProperty(Constants.APP_RADIO_TITLE_KEY_PREFIX + n);
  222.             if (title == null || title.length() == 0) {
  223.                 title = url;
  224.             }
  225.             titles_.addElement(title);
  226.             urls_.addElement(url);
  227.         }
  228.         String localeName = midlet_.getAppProperty(Constants.APP_LOCALE_KEY);
  229.         this.localeName = (localeName != null) ? localeName : Constants.APP_DEFAULT_LOCALE;
  230.     }
  231.     private void loadPlayList() {
  232.         DataInputStream dis;
  233.         RecordStore rs;
  234.         RecordEnumeration e;
  235.         try {
  236.             rs = RecordStore.openRecordStore(Constants.APP_RMS_PLAYLIST, false);
  237.             e = rs.enumerateRecords(null, null, false);
  238.             while (e.hasNextElement()) {
  239.                 dis = new DataInputStream(new ByteArrayInputStream(e.nextRecord()));
  240.                 try {
  241.                     urls_.addElement(dis.readUTF());
  242.                     titles_.addElement(dis.readUTF());
  243.                 } catch (IOException ex) {
  244.                     //
  245.                 }
  246.             }
  247.             e.destroy();
  248.             rs.closeRecordStore();
  249.         } catch (RecordStoreFullException fullStore) {
  250.             //handle a full record store problem
  251.         } catch (RecordStoreNotFoundException notFoundException) {
  252.             //handle store not found which should not happen with the
  253.             //createIfNecessary tag set to true
  254.         } catch (RecordStoreException recordStoreException) {
  255.             //handling record store problems
  256.         }
  257.     }
  258.     private void loadSettings() {
  259.         DataInputStream dis;
  260.         RecordStore rs;
  261.         try {
  262.             rs = RecordStore.openRecordStore(Constants.APP_RMS_SETTINGS, false);
  263.             dis = new DataInputStream(new ByteArrayInputStream(rs.getRecord(SETTING_LOCALE)));
  264.             try {
  265.                 localeName = dis.readUTF();
  266.             } catch (IOException ex) {
  267.             }
  268.             //proceed other settings' records if needed
  269.             rs.closeRecordStore();
  270.         } catch (RecordStoreFullException fullStore) {
  271.             //handle a full record store problem
  272.         } catch (RecordStoreNotFoundException notFoundException) {
  273.             //handle store not found which should not happen with the
  274.             //createIfNecessary tag set to true
  275.         } catch (RecordStoreException recordStoreException) {
  276.             //handling record store problems
  277.         }
  278.     }
  279.     private void storePlayList() {
  280.         byte[] rec;
  281.         ByteArrayOutputStream os;
  282.         DataOutputStream dos;
  283.         RecordStore rs;
  284.         RecordEnumeration e;
  285.         Enumeration urlsEnum = urls_.elements();
  286.         Enumeration titlesEnum = titles_.elements();
  287.         try {
  288.             rs = RecordStore.openRecordStore(Constants.APP_RMS_PLAYLIST, true);
  289.             e = rs.enumerateRecords(null, null, false);
  290.             while (e.hasNextElement() && urlsEnum.hasMoreElements()) {
  291.                 os = new ByteArrayOutputStream();
  292.                 dos = new DataOutputStream(os);
  293.                 try {
  294.                     dos.writeUTF((String) urlsEnum.nextElement());
  295.                     dos.writeUTF((String) titlesEnum.nextElement());
  296.                     dos.close();
  297.                     rec = os.toByteArray();
  298.                     rs.setRecord(e.nextRecordId(), rec, 0, rec.length);
  299.                 } catch (IOException ex) {
  300.                     //
  301.                 } finally {
  302.                     dos = null;
  303.                     os = null;
  304.                 }
  305.             }
  306.             if (urlsEnum.hasMoreElements()) {
  307.                 // add new records
  308.                 while (urlsEnum.hasMoreElements()) {
  309.                     os = new ByteArrayOutputStream();
  310.                     dos = new DataOutputStream(os);
  311.                     try {
  312.                         dos.writeUTF((String) urlsEnum.nextElement());
  313.                         dos.writeUTF((String) titlesEnum.nextElement());
  314.                         dos.close();
  315.                         rec = os.toByteArray();
  316.                         rs.addRecord(rec, 0, rec.length);
  317.                     } catch (IOException ex) {
  318.                         // 
  319.                     } finally {
  320.                         dos = null;
  321.                         os = null;
  322.                     }
  323.                 }
  324.             } else if (e.hasNextElement()) {
  325.                 // delete next records
  326.                 while (e.hasNextElement()) {
  327.                     rs.deleteRecord(e.nextRecordId());
  328.                 }
  329.             }
  330.             e.destroy();
  331.             rs.closeRecordStore();
  332.         } catch (RecordStoreFullException fullStore) {
  333.             //handle a full record store problem
  334.         } catch (RecordStoreNotFoundException notFoundException) {
  335.             //handle store not found which should not happen with the
  336.             //createIfNecessary tag set to true
  337.         } catch (RecordStoreException recordStoreException) {
  338.             //handling record store problems
  339.         } catch (java.lang.NullPointerException npe) {
  340.             //
  341.         }
  342.     }
  343.     private void storeSettings() {
  344.         byte[] rec;
  345.         ByteArrayOutputStream os;
  346.         DataOutputStream dos;
  347.         RecordStore rs;
  348.         try {
  349.             rs = RecordStore.openRecordStore(Constants.APP_RMS_SETTINGS, true);
  350.             try {
  351.                 os = new ByteArrayOutputStream();
  352.                 dos = new DataOutputStream(os);
  353.                 dos.writeUTF(localeName);
  354.                 rec = os.toByteArray();
  355.                 if (rs.getNumRecords() == 0) {
  356.                     rs.addRecord(rec, 0, rec.length);
  357.                     //add other settings data serialy
  358.                 } else {
  359.                     rs.setRecord(SETTING_LOCALE, rec, 0, rec.length);
  360.                     //set other settings data serialy
  361.                 }
  362.                 os.close();
  363.             } catch (IOException ex) {
  364.             }
  365.             rs.closeRecordStore();
  366.         } catch (RecordStoreFullException fullStore) {
  367.             //handle a full record store problem
  368.         } catch (RecordStoreNotFoundException notFoundException) {
  369.             //handle store not found which should not happen with the
  370.             //createIfNecessary tag set to true
  371.         } catch (RecordStoreException recordStoreException) {
  372.             //handling record store problems
  373.         } catch (java.lang.NullPointerException npe) {
  374.             //
  375.         }
  376.     }
  377.     /**
  378.      * Tests if playlist containts station with given URL.
  379.      * @param url URL for check.
  380.      * @return <b>true</b> if playlist containts station with given URL, 
  381.      * <b>false</b> othrwise.
  382.      */
  383.     public boolean hasURL(String url) {
  384.         return urls_.contains(url);
  385.     }
  386.     public String getLocaleName() {
  387.         return localeName;
  388.     }
  389.     public void setLocaleName(String localeName) {
  390.         this.localeName = localeName;
  391.         firePlaylistChanges();
  392.     }
  393. }