Committed the initial version of the UPnP TV bundle (FELIX-52).
It requires org.osgi.core, org.osgi.compendium
A first sample to test the BaseDriver on the OSGi side.
You can use the Intel UpnP Toolkit to listen real devices on the UPnP network.
http://www.intel.com/cd/ids/developer/asmo-na/eng/downloads/upnp/tools/index.htm
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@391458 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/Activator.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/Activator.java
new file mode 100644
index 0000000..1184908
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/Activator.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.util.Dictionary;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.upnp.UPnPDevice;
+
+/**
+ * @author Francesco Furfari
+ */
+
+public class Activator implements BundleActivator {
+
+ static BundleContext context;
+
+ private ServiceRegistration serviceRegistration;
+
+ private TvFrame tvFrame;
+
+ private void doServiceRegistration() {
+ tvFrame = new TvFrame();
+ TvDevice tvDev = tvFrame.getTvDevice();
+ Dictionary dict = tvDev.getDescriptions(null);
+ serviceRegistration = context.registerService(UPnPDevice.class
+ .getName(), tvDev, dict);
+
+ tvFrame.start();
+
+
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ Activator.context = context;
+ doServiceRegistration();
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ serviceRegistration.unregister();
+ tvFrame.stop();
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/EventSource.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/EventSource.java
new file mode 100644
index 0000000..3a21d23
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/EventSource.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.beans.PropertyChangeListener;
+/**
+ * @author Francesco Furfari
+ */
+
+public interface EventSource {
+ void addPropertyChangeListener(PropertyChangeListener listener);
+ void addPropertyChangeListener(String propertyName, PropertyChangeListener listener);
+ void removePropertyChangeListener(PropertyChangeListener listener);
+ void removePropertyChangeListener(String propertyName, PropertyChangeListener listener);
+}
+
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/GetPowerAction.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/GetPowerAction.java
new file mode 100644
index 0000000..61f9ec0
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/GetPowerAction.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+/**
+ * @author Francesco Furfari
+ */
+
+public class GetPowerAction implements UPnPAction {
+
+ final private String NAME = "GetPower";
+ final private String RESULT_STATUS = "Power";
+ final private String[] OUT_ARG_NAMES = new String[]{RESULT_STATUS};
+ private PowerStateVariable power;
+
+
+ public GetPowerAction(PowerStateVariable power){
+ this.power = power;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return OUT_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ return power;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ Boolean value = power.getCurrentPower();
+ Hashtable result = new Hashtable();
+ result.put(RESULT_STATUS,value);
+ return result;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/PowerService.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/PowerService.java
new file mode 100644
index 0000000..ce37959
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/PowerService.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.util.HashMap;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+/**
+ * @author Francesco Furfari
+ */
+
+public class PowerService implements UPnPService {
+ final private String SERVICE_ID = "urn:schemas-upnp-org:serviceId:power:1";
+ final private String SERVICE_TYPE = "urn:schemas-upnp-org:service:power:1";
+ final private String VERSION ="1";
+
+ private PowerStateVariable power;
+ private ResultStateVariable result;
+ private UPnPStateVariable[] states;
+ private HashMap actions = new HashMap();
+
+
+ public PowerService(){
+ power = new PowerStateVariable();
+ result = new ResultStateVariable();
+ this.states = new UPnPStateVariable[]{power,result};
+
+ UPnPAction setPower= new SetPowerAction(power,result);
+ UPnPAction getPower = new GetPowerAction(power);
+ actions.put(setPower.getName(),setPower);
+ actions.put(getPower.getName(),getPower);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getId()
+ */
+ public String getId() {
+ return SERVICE_ID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getType()
+ */
+ public String getType() {
+ return SERVICE_TYPE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getVersion()
+ */
+ public String getVersion() {
+ return VERSION;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getAction(java.lang.String)
+ */
+ public UPnPAction getAction(String name) {
+ return (UPnPAction)actions.get(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getActions()
+ */
+ public UPnPAction[] getActions() {
+ return (UPnPAction[])(actions.values()).toArray(new UPnPAction[]{});
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getStateVariables()
+ */
+ public UPnPStateVariable[] getStateVariables() {
+ return states;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPService#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String name) {
+ if (name.equals("Power"))
+ return power;
+ else if (name.equals("Result"))
+ return result;
+ else return null;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/PowerStateVariable.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/PowerStateVariable.java
new file mode 100644
index 0000000..c84566f
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/PowerStateVariable.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+import java.beans.PropertyChangeEvent;
+/**
+ * @author Francesco Furfari
+ */
+
+public class PowerStateVariable implements UPnPStateVariableDescriptor {
+
+ final private String NAME = "Power";
+ final private Boolean DEFAULT_VALUE = Boolean.FALSE;
+ private UPnPEventNotifier notifier;
+ private Boolean power = Boolean.FALSE;
+
+ public PowerStateVariable(){
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return Boolean.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return TYPE_BOOLEAN;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ return DEFAULT_VALUE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return true;
+ }
+
+ public Boolean getCurrentPower(){
+ return power;
+ }
+
+ public void setPower(Boolean value){
+ if (!value.equals(power)) {
+ Boolean oldValue = power;
+ power = value;
+ if (notifier != null)
+ notifier.propertyChange(new PropertyChangeEvent(this,"Power",oldValue,value));
+ }
+ }
+
+ public void setNotifier(UPnPEventNotifier notifier){
+ this.notifier = notifier;
+ }
+
+ /* (non-Javadoc)
+ * @see it.cnr.isti.niche.osgi.sample.tv.UPnPStateVariableDescriptor#getValue()
+ */
+ public Object getValue() {
+ return power;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/ResultStateVariable.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/ResultStateVariable.java
new file mode 100644
index 0000000..430fbf3
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/ResultStateVariable.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+import org.osgi.service.upnp.UPnPStateVariable;
+/**
+ * @author Francesco Furfari
+ */
+
+public class ResultStateVariable implements UPnPStateVariable{
+
+ final private String NAME = "Result";
+ final private Boolean DEFAULT_VALUE = Boolean.FALSE;
+
+
+ public ResultStateVariable(){
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return Boolean.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return TYPE_BOOLEAN;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ return DEFAULT_VALUE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return false;
+ }
+
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/SetPowerAction.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/SetPowerAction.java
new file mode 100644
index 0000000..944516f
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/SetPowerAction.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+/**
+ * @author Francesco Furfari
+ */
+
+public class SetPowerAction implements UPnPAction {
+
+ final private String NAME = "SetPower";
+ final private String NEW_TIME_VALUE = "Power";
+ final private String NEW_RESULT_VALUE = "Result";
+ final private String[] IN_ARG_NAMES = new String[]{NEW_TIME_VALUE};
+ final private String[] OUT_ARG_NAMES = new String[]{NEW_RESULT_VALUE};
+ private PowerStateVariable power;
+ private ResultStateVariable result;
+
+
+ public SetPowerAction(PowerStateVariable power,ResultStateVariable result){
+ this.power = power;
+ this.result=result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ return "Result";
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+ return IN_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ return OUT_ARG_NAMES;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ if (argumentName.equals("Power")) return power;
+ else if (argumentName.equals("Result")) return result;
+ else return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ Boolean value = (Boolean) args.get(NEW_TIME_VALUE);
+ power.setPower(value);
+ Hashtable result = new Hashtable();
+ result.put(NEW_RESULT_VALUE,Boolean.TRUE);
+ return result;
+ }
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvDevice.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvDevice.java
new file mode 100644
index 0000000..c8c20ec
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvDevice.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.awt.Component;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPIcon;
+import org.osgi.service.upnp.UPnPService;
+/**
+ * @author Francesco Furfari
+ */
+
+public class TvDevice implements UPnPDevice,UPnPEventListener,ServiceListener {
+
+ final private String DEVICE_ID = "uuid:DomoWare-TV";
+ private final static String CLOCK_DEVICE_TYPE = "urn:schemas-upnp-org:device:clock:1";
+ private final static String CLOCK_SERVICE_TYPE = "urn:schemas-upnp-org:service:timer:1";
+
+ private final static String LIGHT_DEVICE_TYPE = "urn:schemas-upnp-org:device:light:1";
+ private final static String LIGHT_SERVICE_TYPE = "urn:schemas-upnp-org:service:power:1";
+
+ private final static String AIRCON_DEVICE_TYPE = "urn:schemas-upnp-org:device:aircon:1";
+ private final static String AIRCON_SERVICE_TYPE = "urn:schemas-upnp-org:service:temp:1";
+
+ private final static String WASHER_DEVICE_TYPE = "urn:schemas-upnp-org:device:washer:1";
+ private final static String WASHER_SERVICE_TYPE = "urn:schemas-upnp-org:service:state:1";
+
+ private final String devicesFilter =
+ "(&"+
+ "("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+"))";
+ /*"(|("+UPnPDevice.TYPE+"="+ CLOCK_SERVICE_TYPE+")"+
+ "("+UPnPDevice.TYPE+"="+ LIGHT_SERVICE_TYPE+")"+
+ "("+UPnPDevice.TYPE+"="+ AIRCON_SERVICE_TYPE+")"+
+ "("+UPnPDevice.TYPE+"="+ WASHER_SERVICE_TYPE+")))";*/
+
+ private BundleContext context;
+ private PowerService powerService;
+ private UPnPService[] services;
+ private Dictionary dictionary;
+ private UPnPEventNotifier notifier;
+ private PowerStateVariable powerState;
+
+ public TvDevice() {
+ powerService = new PowerService();
+ services = new UPnPService[]{powerService};
+ powerState = (PowerStateVariable) powerService.getStateVariable("Power");
+ setupDeviceProperties();
+ buildEventNotifyer();
+ try {
+ Activator.context.addServiceListener(this,devicesFilter);
+ } catch (InvalidSyntaxException e) {
+ System.out.println(e);
+ }
+ }
+
+ /**
+ *
+ */
+ private void buildEventNotifyer() {
+ notifier = new UPnPEventNotifier(Activator.context,this,powerService,null);
+ powerState.setNotifier(notifier);
+ }
+
+ private void setupDeviceProperties(){
+ dictionary = new Properties();
+ dictionary.put(UPnPDevice.UPNP_EXPORT,"");
+ //org.osgi.service.device.Constants.DEVICE_CATEGORY
+ //dictionary.put("DEVICE_CATEGORY","UPnP");
+ dictionary.put(
+ org.osgi.service
+ .device.Constants.DEVICE_CATEGORY,
+ new String[]{UPnPDevice.DEVICE_CATEGORY}
+ );
+ dictionary.put(UPnPDevice.FRIENDLY_NAME,"Domoware Sample Tv");
+ dictionary.put(UPnPDevice.MANUFACTURER,"ISTI-CNR");
+ dictionary.put(UPnPDevice.MANUFACTURER_URL,"http://domoware.isti.cnr.it");
+ dictionary.put(UPnPDevice.MODEL_DESCRIPTION,"A CyberLink Tv device clone to test OSGi to UPnP service import");
+ dictionary.put(UPnPDevice.MODEL_NAME,"BimbiTv");
+ dictionary.put(UPnPDevice.MODEL_NUMBER,"1.0");
+ dictionary.put(UPnPDevice.MODEL_URL,"http://domoware.isti.cnr.it/BimbiTv");
+ dictionary.put(UPnPDevice.PRESENTATION_URL,"http://domoware.isti.cnr.it/BimbiTv/presentation");
+ dictionary.put(UPnPDevice.SERIAL_NUMBER,"123456789");
+ dictionary.put(UPnPDevice.TYPE,"urn:schemas-upnp-org:device:tv:1");
+ dictionary.put(UPnPDevice.UDN,DEVICE_ID);
+ //dictionary.put(UPnPDevice.ID,dictionary.get(UPnPDevice.UDN));
+ dictionary.put(UPnPDevice.UPC,"1213456789");
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getService(java.lang.String)
+ */
+ public UPnPService getService(String serviceId) {
+ if (serviceId.equals(powerService.getId())) return powerService;
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getServices()
+ */
+ public UPnPService[] getServices() {
+ return services;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getIcons(java.lang.String)
+ */
+ public UPnPIcon[] getIcons(String locale) {
+ UPnPIcon icon = new TvIcon();
+ return new UPnPIcon[]{icon} ;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPDevice#getDescriptions(java.lang.String)
+ */
+ public Dictionary getDescriptions(String locale) {
+ return dictionary;
+ }
+
+
+
+ ////////////////////////////////////////////////
+ // Component
+ ////////////////////////////////////////////////
+
+ private Component comp;
+
+ public void setComponent(Component comp)
+ {
+ this.comp = comp;
+ }
+
+ public Component getComponent()
+ {
+ return comp;
+ }
+
+ ////////////////////////////////////////////////
+ // on/off
+ ////////////////////////////////////////////////
+
+ private boolean onFlag = false;
+
+ public void on()
+ {
+ powerState.setPower(Boolean.TRUE);
+ doSubscribe();
+ }
+
+ public boolean isOn()
+ {
+ return powerState.getCurrentPower().booleanValue();
+ }
+ public void off()
+ {
+ powerState.setPower(Boolean.FALSE);
+ undoSubscribe();
+ }
+
+
+ ////////////////////////////////////////////////
+ // Clock
+ ////////////////////////////////////////////////
+
+ private String clockTime = "";
+
+ public String getClockTime()
+ {
+ return clockTime;
+ }
+
+ ////////////////////////////////////////////////
+ // Aircon
+ ////////////////////////////////////////////////
+
+ private String airconTemp = "";
+
+ public String getAirconTempture()
+ {
+ return airconTemp;
+ }
+
+ ////////////////////////////////////////////////
+ // Message
+ ////////////////////////////////////////////////
+
+ private String message = "";
+
+ public void setMessage(String msg)
+ {
+ message = msg;
+ }
+
+ public String getMessage()
+ {
+ return message;
+ }
+
+
+ ////////////////////////////////////////////////
+ // Subscribe
+ ////////////////////////////////////////////////
+
+ private UPnPSubscriber subscriber;
+
+ public void doSubscribe()
+ {
+ subscriber = new UPnPSubscriber(Activator.context,this);
+ subscriber.subscribe(CLOCK_DEVICE_TYPE, CLOCK_SERVICE_TYPE);
+ subscriber.subscribe(AIRCON_DEVICE_TYPE, AIRCON_SERVICE_TYPE);
+ subscriber.subscribe(LIGHT_DEVICE_TYPE, LIGHT_SERVICE_TYPE);
+ subscriber.subscribe(WASHER_DEVICE_TYPE, WASHER_SERVICE_TYPE);
+ }
+
+ public void undoSubscribe(){
+ subscriber.unsubscribe();
+ }
+
+ ArrayList LinkedDevices = new ArrayList();
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPEventListener#notifyUPnPEvent(java.lang.String, java.lang.String, java.util.Dictionary)
+ */
+ public void notifyUPnPEvent(String deviceId, String serviceId, Dictionary events) {
+ if( !LinkedDevices.contains(deviceId))
+ LinkedDevices.add(deviceId);
+ if (deviceId.indexOf("Clock") != -1)
+ clockTime = (String) events.get("Time");
+ else if (deviceId.indexOf("AirCon") != -1)
+ airconTemp = (String) events.get("Temp");
+ else if (deviceId.indexOf("Washer") != -1)
+ message = (String) events.get("State");
+ else if (deviceId.indexOf("Light") != -1)
+ message = (String) events.get("Power");
+
+ comp.repaint();
+ }
+
+
+ ////////////////////////////////////////////////
+ // start/stop
+ ////////////////////////////////////////////////
+
+ public void start()
+ {
+ on();
+ }
+
+ public void stop()
+ {
+ ((PowerStateVariable) powerService.getStateVariable("Power")).setNotifier(null);
+ notifier.destroy();
+ off();
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent event) {
+ switch(event.getType()){
+ case ServiceEvent.REGISTERED:{
+ };break;
+
+ case ServiceEvent.MODIFIED:{
+ };break;
+
+ case ServiceEvent.UNREGISTERING:{
+ ServiceReference sr = event.getServiceReference();
+ String UDN = (String)sr.getProperty(UPnPDevice.ID);
+ if (UDN != null){
+ if (LinkedDevices.contains(UDN)) {
+ if (UDN.indexOf("Clock") != -1)
+ clockTime = "";
+ else if (UDN.indexOf("AirCon") != -1)
+ airconTemp = "";
+ else if (UDN.indexOf("Washer") != -1)
+ message = "";
+ else if (UDN.indexOf("Light") != -1)
+ message = "";
+ }
+ }
+ comp.repaint();
+ };break;
+ }
+ }
+
+}
+
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvFrame.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvFrame.java
new file mode 100644
index 0000000..60a7352
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvFrame.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.awt.BorderLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+
+import org.osgi.framework.BundleException;
+/**
+ * @author Francesco Furfari
+ */
+
+public class TvFrame extends JFrame implements Runnable
+{
+ private final static String TITLE = "DomoWare Sample TV";
+
+ private TvDevice tvDev;
+ private TvPane tvPane;
+
+ public TvFrame()
+ {
+ super(TITLE);
+
+ tvDev = new TvDevice();
+
+ getContentPane().setLayout(new BorderLayout());
+
+ tvPane = new TvPane();
+ tvDev.setComponent(tvPane);
+ tvPane.setDevice(tvDev);
+ getContentPane().add(tvPane, BorderLayout.CENTER);
+
+ addWindowListener(new WindowAdapter(){
+ public void windowClosing(WindowEvent e)
+ {
+ try {
+ Activator.context.getBundle().stop();
+ } catch (BundleException ex) {
+ ex.printStackTrace();
+ }
+ }
+ });
+
+ pack();
+ setVisible(true);
+ }
+
+ public TvPane getTvPanel()
+ {
+ return tvPane;
+ }
+
+ public TvDevice getTvDevice()
+ {
+ return tvDev;
+ }
+
+ ////////////////////////////////////////////////
+ // run
+ ////////////////////////////////////////////////
+
+ private Thread timerThread = null;
+
+ public void run()
+ {
+ Thread thisThread = Thread.currentThread();
+
+ while (timerThread == thisThread) {
+ tvDev.setMessage("");
+ tvPane.repaint();
+ try {
+ Thread.sleep(1000*5);
+ }
+ catch(InterruptedException e) {}
+ }
+ }
+
+ public void start()
+ {
+ tvDev.start();
+
+ timerThread = new Thread(this);
+ timerThread.start();
+ }
+
+ public void stop()
+ {
+ tvDev.stop();
+ timerThread = null;
+ dispose();
+ }
+
+
+}
+
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvIcon.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvIcon.java
new file mode 100644
index 0000000..22de04d
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvIcon.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.osgi.service.upnp.UPnPIcon;
+/**
+ * @author Francesco Furfari
+ */
+
+public class TvIcon implements UPnPIcon {
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getMimeType()
+ */
+ public String getMimeType() {
+ return "image/gif";
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getWidth()
+ */
+ public int getWidth() {
+ return 32;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getHeight()
+ */
+ public int getHeight() {
+ return 32;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getSize()
+ */
+ public int getSize() {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getDepth()
+ */
+ public int getDepth() {
+ return 16;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ return TvIcon.class.getResourceAsStream("images/tv.gif");
+ }
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvPane.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvPane.java
new file mode 100644
index 0000000..0787f69
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/TvPane.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+import javax.imageio.ImageIO;
+import javax.swing.JPanel;
+/**
+ * @author Francesco Furfari
+ */
+
+public class TvPane extends JPanel // MouseListener
+{
+ private final static int IMAGE_BORDER_SIZE = 20;
+ private final static int IMAGE_BOTTOM_BORDER_SIZE = 30;
+
+ ////////////////////////////////////////////////
+ // Constructor
+ ////////////////////////////////////////////////
+
+ public TvPane()
+ {
+ loadImage();
+ initPanel();
+ }
+
+ ////////////////////////////////////////////////
+ // TvDevice
+ ////////////////////////////////////////////////
+
+ private TvDevice tvDev = null;
+
+ public void setDevice(TvDevice dev)
+ {
+ tvDev = dev;
+ }
+
+ public TvDevice getDevice()
+ {
+ return tvDev;
+ }
+
+ ////////////////////////////////////////////////
+ // Background
+ ////////////////////////////////////////////////
+
+ private BufferedImage panelmage;
+ private BufferedImage tvOnImage;
+
+ private void loadImage()
+ {
+ try {
+ panelmage = ImageIO.read(TvPane.class.getResourceAsStream("images/tv.jpg"));
+ tvOnImage = ImageIO.read(TvPane.class.getResourceAsStream("images/tvon.jpg"));
+ }
+ catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+
+ ////////////////////////////////////////////////
+ // Background
+ ////////////////////////////////////////////////
+
+ private void initPanel()
+ {
+ setPreferredSize(new Dimension(panelmage.getWidth(), panelmage.getHeight()));
+ }
+
+ ////////////////////////////////////////////////
+ // Font
+ ////////////////////////////////////////////////
+
+ private final static String DEFAULT_FONT_NAME = "Lucida Console";
+ private final static int DEFAULT_TIME_FONT_SIZE = 10;
+
+ private Font timeFont = null;
+
+ private Font getFont(Graphics g, int size)
+ {
+ Font font = new Font(DEFAULT_FONT_NAME, Font.BOLD, size);
+ if (font != null)
+ return font;
+ return g.getFont();
+ }
+
+ private Font getFont(Graphics g)
+ {
+ if (timeFont == null)
+ timeFont = getFont(g, DEFAULT_TIME_FONT_SIZE);
+ return timeFont;
+ }
+
+ ////////////////////////////////////////////////
+ // paint
+ ////////////////////////////////////////////////
+
+ private void drawClockInfo(Graphics g)
+ {
+ TvDevice tvDev = getDevice();
+
+ int winWidth = getWidth();
+ int winHeight = getHeight();
+
+ Font font = getFont(g);
+ g.setFont(font);
+ FontMetrics fontMetric = g.getFontMetrics();
+ g.setColor(Color.RED);
+
+ Rectangle2D strBounds;
+ int strWidth;
+ int strHeight;
+ int strX;
+ int strY;
+
+ //// Time String ////
+
+ String timeStr = tvDev.getClockTime();
+ if (timeStr != null && 0 < timeStr.length()) {
+ strBounds = fontMetric.getStringBounds(timeStr, g);
+ strWidth = (int)strBounds.getWidth();
+ strHeight = (int)strBounds.getHeight();
+ strX = IMAGE_BORDER_SIZE;
+ strY = IMAGE_BORDER_SIZE + strHeight;
+ g.drawString(
+ timeStr,
+ strX,
+ strY);
+ }
+
+ //// Tempture String ////
+
+ String tempStr = tvDev.getAirconTempture();
+ if (tempStr != null && 0 < tempStr.length()) {
+ tempStr += "C";
+ strBounds = fontMetric.getStringBounds(tempStr, g);
+ strWidth = (int)strBounds.getWidth();
+ strHeight = (int)strBounds.getHeight();
+ strX = winWidth - IMAGE_BORDER_SIZE - strWidth;
+ strY = IMAGE_BORDER_SIZE + strHeight;
+ g.drawString(
+ tempStr,
+ strX,
+ strY);
+ }
+
+ //// Message String ////
+
+ String msgStr = tvDev.getMessage();
+ if (msgStr != null && 0 < msgStr.length()) {
+ strBounds = fontMetric.getStringBounds(msgStr, g);
+ strWidth = (int)strBounds.getWidth();
+ strHeight = (int)strBounds.getHeight();
+ strX = IMAGE_BORDER_SIZE;
+ strY = getHeight()-IMAGE_BOTTOM_BORDER_SIZE-2;
+ g.drawString(
+ msgStr,
+ strX,
+ strY);
+ }
+ }
+
+ private void drawTvImage(Graphics g)
+ {
+ //g.setColor(Color.WHITE);
+ //g.clearRect(IMAGE_BORDER_SIZE, IMAGE_BORDER_SIZE, getWidth()-IMAGE_BORDER_SIZE*2, getHeight()-IMAGE_BORDER_SIZE-IMAGE_BOTTOM_BORDER_SIZE);
+ g.drawImage(tvOnImage, IMAGE_BORDER_SIZE, IMAGE_BORDER_SIZE, null);
+ }
+
+ private void clear(Graphics g)
+ {
+ g.setColor(Color.GRAY);
+ g.clearRect(0, 0, getWidth(), getHeight());
+ }
+
+
+ private void drawPanelImage(Graphics g)
+ {
+ g.drawImage(panelmage, 0, 0, null);
+ }
+
+ public void paint(Graphics g)
+ {
+ clear(g);
+ drawPanelImage(g);
+ TvDevice tvDev = getDevice();
+ if (tvDev.isOn() == true) {
+ drawTvImage(g);
+ drawClockInfo(g);
+ }
+ }
+}
+
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPEventNotifier.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPEventNotifier.java
new file mode 100644
index 0000000..58a48a5
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPEventNotifier.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Dictionary;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/**
+ * @author Francesco Furfari
+ */
+
+public class UPnPEventNotifier implements PropertyChangeListener,ServiceListener {
+ BundleContext context;
+ UPnPDevice device;
+ UPnPService service;
+ EventSource source;
+
+ Properties UPnPTargetListener;
+ String deviceId;
+ String serviceId;
+ Vector upnpListeners = new Vector();
+
+ public UPnPEventNotifier(BundleContext context,UPnPDevice device,UPnPService service,EventSource source){
+ this.context=context;
+ this.device=device;
+ this.service=service;
+ this.source=source;
+ this.serviceId=service.getId();
+ setupUPnPListenerHouseKeeping(device);
+ }
+
+ /**
+ * @param deviceId
+ */
+ private void setupUPnPListenerHouseKeeping(UPnPDevice device) {
+ UPnPTargetListener = new Properties();
+ Dictionary dict = device.getDescriptions(null);
+ deviceId = (String) dict.get(UPnPDevice.ID);
+ UPnPTargetListener.put(UPnPDevice.ID,deviceId);
+ UPnPTargetListener.put(UPnPService.ID,serviceId);
+ UPnPTargetListener.put(UPnPDevice.TYPE,dict.get(UPnPDevice.TYPE));
+ UPnPTargetListener.put(UPnPService.TYPE,service.getType());
+ String ANY_UPnPEventListener = "("+Constants.OBJECTCLASS+"="+UPnPEventListener.class.getName()+")";
+
+ ServiceReference[] listeners = null;
+ try {
+ listeners = context.getServiceReferences(UPnPEventListener.class.getName(),null);
+ if (listeners != null){
+ for (int i = 0;i<listeners.length;i++){
+ ServiceReference sr = listeners[i];
+ Filter filter = (Filter) sr.getProperty(UPnPEventListener.UPNP_FILTER);
+ if (filter == null) addNewListener(sr);
+ else {
+ if (filter.match(UPnPTargetListener))
+ addNewListener(sr);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ try {
+ //String filter = "(&" + ANY_UPnPEventListener + deviceId_Filter + ")";
+ String filter = ANY_UPnPEventListener;
+ context.addServiceListener(this,filter);
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ if (source!=null){
+ UPnPStateVariable[] vars = service.getStateVariables();
+ if (vars != null){
+ for (int i=0;i<vars.length;i++)
+ if(vars[i].sendsEvents())
+ source.addPropertyChangeListener(vars[i].getName(),this);
+ }
+ }
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+ Iterator list = upnpListeners.iterator();
+ String property = evt.getPropertyName();
+ Object value = evt.getNewValue();
+ String valueString = value.toString();
+ final Properties events = new Properties();
+ events.put(property,valueString);
+ while (list.hasNext()){
+ final ServiceReference sr = (ServiceReference)list.next();
+ String[] props =sr.getPropertyKeys();
+ new Thread(null,null,"Notifier"){
+ public void run(){
+ try {
+ UPnPEventListener listener = (UPnPEventListener) context.getService(sr);
+ listener.notifyUPnPEvent(deviceId,serviceId,events);
+ context.ungetService(sr);
+ } catch (Exception ex){
+ System.out.println("TV UPnPEventNotifier Err: " +ex);
+ System.out.println("context: " +context);
+ System.out.println("listener: " +context.getService(sr));
+ System.out.println("sr: " +sr);
+ }
+ }
+ }.start();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch(e.getType()){
+ case ServiceEvent.REGISTERED:{
+ ServiceReference sr = e.getServiceReference();
+ Filter filter = (Filter) sr.getProperty(UPnPEventListener.UPNP_FILTER);
+ if (filter == null) addNewListener(sr);
+ else {
+ if (filter.match(UPnPTargetListener))
+ addNewListener(sr);
+ }
+ };break;
+
+ case ServiceEvent.MODIFIED:{
+ };break;
+
+ case ServiceEvent.UNREGISTERING:{
+ removeListener(e.getServiceReference());
+ };break;
+
+ }
+
+ }
+
+ /**
+ * @param reference
+ */
+ private void removeListener(ServiceReference reference) {
+ upnpListeners.remove(reference);
+ }
+
+ /**
+ * @param reference
+ */
+ private void addNewListener(ServiceReference reference) {
+ upnpListeners.add(reference);
+ UPnPStateVariable[] vars = service.getStateVariables();
+ if (vars != null){
+ for (int i=0;i<vars.length;i++)
+ if(vars[i].sendsEvents()){
+ Object value = ((UPnPStateVariableDescriptor) vars[i]).getValue();
+ propertyChange(new PropertyChangeEvent(this,vars[i].getName(),value,value));
+ }
+ }
+ }
+
+ public void destroy(){
+ context.removeServiceListener(this);
+ upnpListeners.removeAllElements();
+ }
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPStateVariableDescriptor.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPStateVariableDescriptor.java
new file mode 100644
index 0000000..b08d4bc
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPStateVariableDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/**
+ * UPnPStateVariableDescriptor.java 22-gen-2005
+ * @author Francesco Furfari
+ */
+public interface UPnPStateVariableDescriptor extends UPnPStateVariable {
+ Object getValue();
+
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPSubscriber.java b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPSubscriber.java
new file mode 100644
index 0000000..34f5313
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/java/org/apache/felix/upnp/sample/tv/UPnPSubscriber.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.felix.upnp.sample.tv;
+
+import java.util.Properties;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPService;
+
+/**
+ * @author Francesco Furfari
+ */
+
+public class UPnPSubscriber {
+ ServiceRegistration registration = null;
+ BundleContext context;
+ UPnPEventListener listener;
+
+ public UPnPSubscriber(BundleContext context,UPnPEventListener listener){
+ this.context = context;
+ this.listener = listener;
+ }
+
+ public void subscribe(String deviceType, String serviceType){
+ String keys = "(&(" + UPnPDevice.TYPE + "="+ deviceType + ")(" + UPnPService.TYPE + "=" + serviceType + "))";
+ try {
+ Filter filter = context.createFilter(keys);
+ Properties props = new Properties();
+ props.put(UPnPEventListener.UPNP_FILTER, filter);
+ registration = context.registerService(UPnPEventListener.class.getName(), listener, props);
+ }catch (Exception ex){
+ System.out.println(ex);
+ }
+ }
+
+ public void unsubscribe(){
+ registration.unregister();
+ registration = null;
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.sample.tv/src/main/resources/META-INF/Manifest.mf b/org.apache.felix.upnp.sample.tv/src/main/resources/META-INF/Manifest.mf
new file mode 100644
index 0000000..cc0e51c
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/resources/META-INF/Manifest.mf
@@ -0,0 +1,4 @@
+Bundle-Author: Matteo Demuru <matte-d@users.sourceforge.net>,
+ Stefano "Kismet" Lenzi <kismet-sl@users.sourceforge.net>,
+ Francesco Furfari <francesco.furfari@isti.cnr.it>,
+Bundle-ClassPath: .
diff --git a/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.gif b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.gif
new file mode 100644
index 0000000..21327fc
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.gif
Binary files differ
diff --git a/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.jpg b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.jpg
new file mode 100644
index 0000000..5882710
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.jpg
Binary files differ
diff --git a/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.psd b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.psd
new file mode 100644
index 0000000..f5e03a8
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tv.psd
Binary files differ
diff --git a/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tvon.jpg b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tvon.jpg
new file mode 100644
index 0000000..b3fb3cc
--- /dev/null
+++ b/org.apache.felix.upnp.sample.tv/src/main/resources/org/apache/felix/upnp/sample/tv/images/tvon.jpg
Binary files differ