1. Identifying the underlying bearer, ESG spec used in the implementation:
import javax.microedition.broadcast.esg; ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); MetadataSet spec; MetadataSet[] speclist = esg.getSupportedMetadataSets(); for (int i = 0; i < speclist.length; i++) { System.out.println("Metadata Specification: " + speclist[i].getDescription()); // Check the class for the different types of spec; DVBH in this case. if (speclist[i] instanceof CommonMetadataSet) { // .... } }
2. Enumerate all the valid attributes in the specs:
ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); MetadataSet spec; MetadataSet[] speclist = esg.getSupportedMetadataSets(); for (int i = 0; i < speclist.length; i++) { Attribute[] attrs = speclist[i].getValidAttributes(); for (int j = 0; j < attrs.length; j++) { // Eumerate the attributes and print out their long (proper) names. System.out.println("Attribute: " + attrs[j].getName()); } }
3. Find all the programs of a particular genre, then display it:
// Form the query ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); Query q = QueryComposer.equivalent(CommonMetadataSet.PROGRAM_CONTENT_GENRE, "News"); // Because some programs of our interest may be updated asynchronously, // we should also add a listener to make sure that we get updated // on all the programs we are interested in. // We'll go through this in Example 4. try { esg.addListener(new ProgramMonitor(), q); } catch (QueryException qe) { // invalid query } ProgramEvent programs[]; try { // Find the programs programs = esg.findPrograms(q); for (int i = 0; i < programs.length; i++) { // A custom function to display the program info // Example 5. displayProgramInfo(programs[i]); } } catch (QueryException e) { }
4. Listen to program updates:
// Define my own program change listener for monitoring // program updates. class ProgramMonitor implements ServiceGuideListener { public void serviceGuideUpdated(String event, ServiceGuideData esgdata, Object data) { if (event == NEW_PROGRAM_LISTED || event == PROGRAM_CHANGED) { // Display the new program displayProgramInfo(esgdata); } else if (event == SERVICE_GUIDE_BULK_CHANGED || event == PROGRAM_DELETED) { // We'll need to redo the queries and redisplay // the programs. See Example 3. } } }
5. Display "Generic" program information:
void displayProgramInfo(ProgramEvent p) { Attribute[] attrs = CommonMetadataSet.getInstance().getValidAttributes(); for (int i = 0; i < attrs.length; i++) { // Since we do not know ahead of time what the type // of the attributes are, we will need to test for // them one by one with "instanceof". // The following format* methods format and display the // values in some meaningful ways in the GUI. They are // left as exercise for the readers. formatAttribute(attrs[i].getName()); if (attrs[i] instanceof StringAttribute) { formatString(p.getValue((StringAttribute)attrs[i])); } else if (attrs[i] instanceof DateAttribute) { formatDate(p.getValue((DateAttribute)attrs[i])); } // More... } }
6. Display the Electronic Service Guide in the traditional time listing format:
ServiceGuide esg; // Listen for all incoming programs. // Listener to be defined later. try { esg.addListener(new ProgramMonitor(), null); } catch(QueryException qe) {} void displayServiceGuide() { Attribute[] sortBy = new Attribute[] { CommonMetadataSet.SERVICE_ID, CommonMetadataSet.PROGRAM_START_TIME }; try { // Select all programs and sort them first by their service ids, // then the scheduled start time. ProgramEvent[] programs = esg.findPrograms(null, sortBy, 0, 0); for (int i = 0; i < programs.length; i++) displayProgramInfo(programs[i]); } catch (QueryException e) { } } public class ProgramMonitor implements ServiceGuideListener { public void serviceGuideUpdated(String event, ServiceGuideData esgdata, Object data) { if (event == NEW_PROGRAM_LISTED || event == PROGRAM_DELETED || event == SERVICE_GUIDE_UPDATE_COMPLETED) { // It is easier to simply update the entire list // and get the display sorted properly. displayServiceGuide(); } else if (event == PROGRAM_CHANGED) { // Display the changed program displayProgramInfo(esgdata); } } }
7. Create query to get all programs today on PRO7 between 6 pm and 10 pm:
// calculate the dates for 6 pm and 10 pm today Calendar c = Calendar.getInstance(); // use 17:59:59 instead of 18:00:00 to get programs starting 6 pm exactly c.set(Calendar.HOUR, 17); c.set(Calendar.MINUTE, 59); c.set(Calendar.SECOND, 59); Date startTime = c.getTime(); c.set(Calendar.HOUR, 22); c.set(Calendar.MINUTE, 00); c.set(Calendar.SECOND, 00); Date endTime = c.getTime(); // create queries Query qChannel = QueryComposer.equivalent(CommonMetadataSet.SERVICE_NAME, "PRO7"); Query qAfter = QueryComposer.after(CommonMetadataSet.PROGRAM_START_TIME, startTime); Query qBefore = QueryComposer.before(CommonMetadataSet.PROGRAM_END_TIME, endTime); // combine queries to one Query q = QueryComposer.and(qChannel, QueryComposer.and(qAfter, qBefore)); ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); ProgramEvent programs[]; try { // Find the programs programs = esg.findPrograms(q); for (int i = 0; i < programs.length; i++) { displayProgramInfo(programs[i]); } } catch (QueryException e) { }
8. Create query to get all programs on YLE in Finnish or Swedish
// find all multilingual programs, both in Finnish and Swedish, on YLE Query qChannel = QueryComposer.equivalent(CommonMetadataSet.SERVICE_NAME, "YLE"); Query qFinnish = QueryComposer.equivalent(CommonMetadataSet.SERVICE_COMPONENT_LANGUAGE, "fin"); Query qSwedish = QueryComposer.equivalent(CommonMetadataSet.SERVICE_COMPONENT_LANGUAGE, "swe"); // combine queries to one Query q = QueryComposer.and(qChannel, QueryComposer.and(qFinnish, qSwedish)); ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); ProgramEvent programs[]; try { // Find the programs programs = esg.findPrograms(q); for (int i = 0; i < programs.length; i++) { displayProgramInfo(programs[i]); } } catch (QueryException e) { }
9. Changing the current service of the context where the calling application belong:
ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); try { Service[] current = esg.findServices(QueryComposer.currentProgram()); ServiceContext sc = ServiceContext.getDefaultContext(); sc.select(current[0]); } catch (Exception e) { }
10. Selecting a service based on the ESG:
ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); Query q = QueryComposer.equivalent(CommonMetadataSet.SERVICE_NAME, "BBC"); try { Service[] services = esg.findServices(q); if (services.length > 0) { ServiceContext sc = ServiceContext.getDefaultContext(); sc.select(services[0]); } } catch (Exception e) { }
11. Selecting a service and fetch the Players for presentation
import javax.microedition.broadcast.*; import javax.microedition.broadcast.esg.*; import javax.microedition.media.*; import javax.microedition.media.control.*; ServiceContext sc = ServiceContext.getDefaultContext(); /** * Add a listener to be notified of the creation of the Players. * Initialize and start the Players as they are created. */ sc.addListener(new ServiceContextListener() { public void contextUpdate(ServiceContext s, String event, Object data) { if (event == ServiceContextListener.PLAYERS_REALIZED) { Player players[] = (Player [])data; // The players should all be realized at this point. // Initialize and display them. for (int i = 0; i < players.length; i++) { VideoControl vc = (VideoControl)players[i].getControl("VideoControl"); if (vc != null) { vc.initDisplayMode(vc.USE_DIRECT_VIDEO, canvas /* a GUI canvas created ahead of time */); vc.setVisible(true); } } } } }); // Select a service. ServiceGuide esg = ServiceGuide.getDefaultServiceGuide(); try { Service[] current = esg.findServices(QueryComposer.currentProgram()); sc.select(current[0]); } catch (QueryException qe) {}
12. Using AMMS controls
import javax.microedition.broadcast.*; import javax.microedition.media.*; import javax.microedition.amms.control.audioeffect.*; import javax.microedition.amms.control.imageeffect.*; // Fetch EqualizerControl from a realized Player that was fetched // from ServiceContext as in example 11. EqualizerControl eq = (EqualizerControl)player.getControl("javax.microedition.amms.control.audioeffect.EqualizerControl"); if (eq != null) { // Equalizer is supported. // Let's boost the bass a little bit: eq.setBass(70); eq.setEnabled(true); } // Similarly , fetch an ImageTonalityControl. ImageTonalityControl it = (ImageTonalityControl)player.getControl("javax.microedition.amms.control.audioeffect.ImageTonalityControl"); if (it != null) { // Image tonality settings are supported. // Let's increase image contrast: it.setContrast(75); it.setEnabled(true); }
13. Working with Broadcast Objects: Retrieving typed packet streams
import javax.microedition.broadcast.*; import javax.microedition.broadcast.connection.*; import java.util.*; /** * Return all packet streams found in this service. * This example excludes files and directories and includes * available raw data from A/V components. * * @return a list of all available packet streams */ public Vector getTypedPacketStreams() { // request the default service context ServiceContext serviceContext = ServiceContext.getDefaultContext(); // get all selected components ServiceComponent[] components = serviceContext.getSelectedComponents(); Vector connections = new Vector(); for (int i = 0; i < components.length; i++) { try { BroadcastConnection connection = serviceContext.getBroadcastDatagramConnection(components[i]); // only add datagram connections to the list connections.addElement(components[i]); } catch (BroadcastServiceException e) { // ignore connections that cannot be retrieved from the context } } return connections; } /** * Return all auxiliary packet data connections of a certain type. */ public Vector getPacketStream(String mimeType) { Vector packetStreams = getPacketStreams(); Vector typedPacketStreams = new Vector(); Enumeration packetStreamEnum = packetStreams.elements(); while(packetStreamEnum.hasMoreElements()) { BroadcastDatagramConnection connection = (BroadcastDatagramConnection)packetStreamEnum.nextElement(); // selectively add only connections of a certain mime type if(connection.getMimeType().startsWith(mimeType)) { typesPacketStreams.addElement(connection); } } return typedPacketStreams; }
14. Working with Auxiliary Data: Getting an Auxiliary Service Logo
import javax.microedition.broadcast.*; import javax.microedition.broadcast.esg.*; import javax.microedition.broadcast.connection.*; import javax.microedition.io.*; import java.io.*; /** * This method retrieves the logo associated with a service. */ public InputConnection getServiceLogo() throws IOException, QueryException { // request the default service context ServiceContext serviceContext = ServiceContext.getDefaultContext(); // Retrieve content logo uri String logoUri = serviceContext.getService().getStringValue(CommonMetadataSet.PROGRAM_CONTENT_AUX_LOGO); // Open the URI. The URI could be http, file or carousel-based. // So we'll cast and use it as an InputConnection. if (logoUri == null) return null; Connection logoConnection = Connector.open(logoUri, Connector.READ); if (logoConnection instanceof InputConnection) { return (InputConnection) logoConnection; } return null; } /** * Just a skeleton to handle the service logo. */ public void handleServiceLogo() { try { InputConnection ic = getServiceLogo(); // We may want to specialize the code here. if (ic instanceof HttpConnection) { // Do something specific for http. } else if (ic instanceof BroadcastFileConnection) { // Do something specific for carousel. BroadcastFileConnection bfc = (BroadcastFileConnection)ic; if (!bfc.isAvailable()) bfc.addListener(myLogoListener); else { // Get additional information like mimetype and load image. } } } catch (Exception e) { } }
15. Subscribe to a "premium movie service"
ServiceGuide db = ServiceGuide.getDefaultServiceGuide(); Query q = QueryComposer.equivalent(CommonMetadataSet.SERVICE_NAME, "PremiumMovies"); try { Service[] services = db.findServices(q); if (services.length > 0) { Service premium = services[0]; String premiumServiceID = services[0].getStringValue(CommonMetadataSet.SERVICE_ID); PurchaseObjects[] purchaseObjects = SubscriptionManager.getPurchaseObjects(serviceId); if(purchaseObjects.length > 0) { // show the content of the purchaseObjects to the user and // and let him choose // let's assume that the first purhchaseObject was selected by the user if (purchaseObjects[0].isPurchased()) { // user has already subscribed to the service, no need to buy it again return; } purchaseObjects[0].addPurchaseListener(this); // assume that the options are known to the user requestPriceOptions() is not needed PriceOption[] options = purchaseObjects[0].getPriceOptions(); // at this point the different options should be presented to the user purchaseObjects[0].purchase(options[0]); // purchase transaction has been started. // implementation pops up a dialog to get confirmation from the user // application can now just wait for it to complete } } } catch (Exception e) { } void purchaseResponse(PurchaseObject source, java.lang.String event, java.lang.Object object) { if (event.equals(PURCHASE_STARTED)) { // purchase process started return; } if (event.equals(PURCHASE_DENIED)) { // user denied the purchasing return; } if (event.equals(PURCHASE_APPROVED)) { // user denied the purchasing return; } if (event.equals(PURCHASE_COMPLETED)) { // user denied the purchasing return; } if (event.equals(PURCHASE_FAILED)) { // user denied the purchasing return; } }