/* This file is part of JFLICKS. JFLICKS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JFLICKS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JFLICKS. If not, see <http://www.gnu.org/licenses/>. */ package org.jflicks.nms; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import javax.imageio.ImageIO; import org.jflicks.autoart.AutoArt; import org.jflicks.cleaner.Cleaner; import org.jflicks.configure.BaseConfig; import org.jflicks.configure.Configuration; import org.jflicks.configure.NameValue; import org.jflicks.photomanager.Photo; import org.jflicks.photomanager.PhotoManager; import org.jflicks.photomanager.Tag; import org.jflicks.trailer.Trailer; import org.jflicks.tv.Airing; import org.jflicks.tv.Channel; import org.jflicks.tv.ChannelLogo; import org.jflicks.tv.Listing; import org.jflicks.tv.LiveTV; import org.jflicks.tv.Recording; import org.jflicks.tv.RecordingRule; import org.jflicks.tv.Show; import org.jflicks.tv.ShowAiring; import org.jflicks.tv.Task; import org.jflicks.tv.Upcoming; import org.jflicks.tv.live.Live; import org.jflicks.tv.ondemand.OnDemand; import org.jflicks.tv.ondemand.StreamSession; import org.jflicks.tv.programdata.DataUpdateEvent; import org.jflicks.tv.programdata.DataUpdateListener; import org.jflicks.tv.programdata.ProgramData; import org.jflicks.tv.postproc.PostProc; import org.jflicks.tv.postproc.worker.Worker; import org.jflicks.tv.recorder.BaseRecorder; import org.jflicks.tv.recorder.RecorderBean; import org.jflicks.tv.recorder.Recorder; import org.jflicks.tv.scheduler.RecordedShow; import org.jflicks.tv.scheduler.Scheduler; import org.jflicks.util.EventSender; import org.jflicks.util.StartsWithFilter; import org.jflicks.util.LogUtil; import org.jflicks.util.Util; import org.jflicks.videomanager.VideoManager; /** * This class is a base implementation of the NMS interface. * * @author Doug Barnum * @version 1.0 */ public abstract class BaseNMS extends BaseConfig implements NMS, DataUpdateListener { private String title; private String host; private String groupName; private int port; private int httpPort; private Scheduler scheduler; private PostProc postProc; private Live live; private Cleaner cleaner; private PhotoManager photoManager; private VideoManager videoManager; private AutoArt autoArt; private ArrayList<Recorder> recorderList; private ArrayList<ProgramData> programDataList; private ArrayList<OnDemand> onDemandList; private ArrayList<Trailer> trailerList; private ArrayList<Recording> removeRecordingList; private EventSender eventSender; private HashMap<Channel, ArrayList<ShowAiring>> showAiringCacheMap; /** * Simple empty constructor. */ public BaseNMS() { setRecorderList(new ArrayList<Recorder>()); setProgramDataList(new ArrayList<ProgramData>()); setOnDemandList(new ArrayList<OnDemand>()); setTrailerList(new ArrayList<Trailer>()); setRemoveRecordingList(new ArrayList<Recording>()); setShowAiringCacheMap(new HashMap<Channel, ArrayList<ShowAiring>>()); } /** * {@inheritDoc} */ public Scheduler getScheduler() { return (scheduler); } /** * Convenience method to set the Scheduler property. * * @param s A given Scheduler instance. */ public void setScheduler(Scheduler s) { scheduler = s; if (s != null) { s.setNMS(this); Configuration def = s.getDefaultConfiguration(); save(def, false); s.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public Live getLive() { return (live); } /** * Convenience method to set the Live property. * * @param l A given Live instance. */ public void setLive(Live l) { live = l; if (l != null) { l.setNMS(this); Configuration def = l.getDefaultConfiguration(); save(def, false); l.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public Cleaner getCleaner() { return (cleaner); } /** * Convenience method to set the Cleaner property. * * @param c A given Cleaner instance. */ public void setCleaner(Cleaner c) { cleaner = c; if (c != null) { c.setNMS(this); Configuration def = c.getDefaultConfiguration(); save(def, false); c.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public PhotoManager getPhotoManager() { return (photoManager); } /** * Convenience method to set the PhotoManager property. * * @param p A given PhotoManager instance. */ public void setPhotoManager(PhotoManager p) { photoManager = p; if (p != null) { p.setNMS(this); Configuration def = p.getDefaultConfiguration(); save(def, false); p.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public VideoManager getVideoManager() { return (videoManager); } /** * Convenience method to set the VideoManager property. * * @param vm A given VideoManager instance. */ public void setVideoManager(VideoManager vm) { videoManager = vm; if (vm != null) { vm.setNMS(this); Configuration def = vm.getDefaultConfiguration(); save(def, false); vm.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public AutoArt getAutoArt() { return (autoArt); } /** * Convenience method to set the AutoArt property. * * @param aa A given AutoArt instance. */ public void setAutoArt(AutoArt aa) { autoArt = aa; if (aa != null) { aa.setNMS(this); Configuration def = aa.getDefaultConfiguration(); save(def, false); aa.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public PostProc getPostProc() { return (postProc); } /** * Convenience method to set the PostProc property. * * @param pp A given PostProc instance. */ public void setPostProc(PostProc pp) { postProc = pp; if (pp != null) { pp.setNMS(this); Configuration def = pp.getDefaultConfiguration(); save(def, false); pp.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * {@inheritDoc} */ public Task[] getTasks() { Task[] result = null; PostProc pp = getPostProc(); if (pp != null) { Worker[] array = pp.getWorkers(); if (array != null) { result = new Task[array.length]; for (int i = 0; i < result.length; i++) { result[i] = new Task(); result[i].setTitle(array[i].getTitle()); result[i].setDescription(array[i].getDescription()); result[i].setDefaultRun(array[i].isDefaultRun()); result[i].setRun(array[i].isDefaultRun()); result[i].setSelectable(array[i].isUserSelectable()); result[i].setIndexer(array[i].isIndexer()); result[i].setCommercialDetector(array[i].isCommercialDetector()); } } } return (result); } private ArrayList<Recorder> getRecorderList() { return (recorderList); } private void setRecorderList(ArrayList<Recorder> l) { recorderList = l; } private ArrayList<ProgramData> getProgramDataList() { return (programDataList); } private void setProgramDataList(ArrayList<ProgramData> l) { programDataList = l; } private ArrayList<Trailer> getTrailerList() { return (trailerList); } private void setTrailerList(ArrayList<Trailer> l) { trailerList = l; } /** * We have a current list of Recordings to be removed. * * @return A List of Recording instances. */ public ArrayList<Recording> getRemoveRecordingList() { return (removeRecordingList); } private void setRemoveRecordingList(ArrayList<Recording> l) { removeRecordingList = l; } private HashMap<Channel, ArrayList<ShowAiring>> getShowAiringCacheMap() { return (showAiringCacheMap); } private void setShowAiringCacheMap( HashMap<Channel, ArrayList<ShowAiring>> m) { showAiringCacheMap = m; } private void clearShowAiringCacheMap() { HashMap<Channel, ArrayList<ShowAiring>> m = getShowAiringCacheMap(); if (m != null) { m.clear(); } } private ArrayList<ShowAiring> getShowAiringListByChannel(Channel c) { ArrayList<ShowAiring> result = null; HashMap<Channel, ArrayList<ShowAiring>> m = getShowAiringCacheMap(); if ((c != null) && (m != null)) { result = m.get(c); } return (result); } private void addShowAiringListByChannel(Channel c, ArrayList<ShowAiring> l) { HashMap<Channel, ArrayList<ShowAiring>> m = getShowAiringCacheMap(); if ((c != null) && (l != null) && (m != null)) { m.put(c, l); } } private ArrayList<OnDemand> getOnDemandList() { return (onDemandList); } private void setOnDemandList(ArrayList<OnDemand> l) { onDemandList = l; } /** * Convenience method for extensions to add a recorder instance. * * @param r A Recorder to add. */ public void addRecorder(Recorder r) { ArrayList<Recorder> l = getRecorderList(); if ((l != null) && (r != null)) { l.add(r); Collections.sort(l, new RecorderSortByTitleDevice()); Configuration def = r.getDefaultConfiguration(); save(def, false); r.setConfiguration(getConfigurationBySource(def.getSource())); if (r instanceof BaseRecorder) { BaseRecorder br = (BaseRecorder) r; br.setNMS(this); } } } /** * Convenience method for extensions to remove a recorder instance. * * @param r A Recorder to remove. */ public void removeRecorder(Recorder r) { ArrayList<Recorder> l = getRecorderList(); if ((l != null) && (r != null)) { l.remove(r); } } /** * Convenience method for extensions to add a ProgramData instance. * * @param pd A ProgramData to add. */ public void addProgramData(ProgramData pd) { ArrayList<ProgramData> l = getProgramDataList(); if ((l != null) && (pd != null)) { pd.addDataUpdateListener(this); l.add(pd); Configuration def = pd.getDefaultConfiguration(); save(def, false); pd.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * Convenience method for extensions to remove a ProgramData instance. * * @param pd A ProgramData to remove. */ public void removeProgramData(ProgramData pd) { ArrayList<ProgramData> l = getProgramDataList(); if ((l != null) && (pd != null)) { l.remove(pd); } } /** * Convenience method for extensions to add a OnDemand instance. * * @param o A OnDemand to add. */ public void addOnDemand(OnDemand o) { ArrayList<OnDemand> l = getOnDemandList(); if ((l != null) && (o != null)) { l.add(o); o.setNMS(this); Configuration def = o.getDefaultConfiguration(); save(def, false); o.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * Convenience method for extensions to remove a OnDemand instance. * * @param o A OnDemand to remove. */ public void removeOnDemand(OnDemand o) { ArrayList<OnDemand> l = getOnDemandList(); if ((l != null) && (o != null)) { l.remove(o); } } /** * {@inheritDoc} */ public OnDemand[] getOnDemands() { OnDemand[] result = null; ArrayList<OnDemand> l = getOnDemandList(); if ((l != null) && (l.size() > 0)) { result = l.toArray(new OnDemand[l.size()]); } return (result); } /** * Convenience method for extensions to add a Trailer instance. * * @param t A Trailer to add. */ public void addTrailer(Trailer t) { ArrayList<Trailer> l = getTrailerList(); if ((l != null) && (t != null)) { l.add(t); t.setNMS(this); Configuration def = t.getDefaultConfiguration(); save(def, false); t.setConfiguration(getConfigurationBySource(def.getSource())); } } /** * Convenience method for extensions to remove a Trailer instance. * * @param t A Trailer to remove. */ public void removeTrailer(Trailer t) { ArrayList<Trailer> l = getTrailerList(); if ((l != null) && (t != null)) { l.remove(t); } } /** * {@inheritDoc} */ public Trailer[] getTrailers() { Trailer[] result = null; ArrayList<Trailer> l = getTrailerList(); if ((l != null) && (l.size() > 0)) { result = l.toArray(new Trailer[l.size()]); } return (result); } /** * {@inheritDoc} */ public String getTitle() { return (title); } /** * Convenience method to set this property. * * @param s The given title value. */ public void setTitle(String s) { title = s; } /** * {@inheritDoc} */ public Recorder[] getRecorders() { Recorder[] result = null; ArrayList<Recorder> l = getRecorderList(); if ((l != null) && (l.size() > 0)) { RecorderBean[] beans = new RecorderBean[l.size()]; for (int i = 0; i < beans.length; i++) { beans[i] = new RecorderBean(l.get(i)); } result = beans; } return (result); } /** * {@inheritDoc} */ public Recorder[] getConfiguredRecorders() { Recorder[] result = null; Scheduler s = getScheduler(); if (s != null) { Recorder[] array = s.getConfiguredRecorders(); if ((array != null) && (array.length > 0)) { RecorderBean[] beans = new RecorderBean[array.length]; for (int i = 0; i < beans.length; i++) { beans[i] = new RecorderBean(array[i]); LogUtil.log(LogUtil.DEBUG, "RecorderBean isRecording: " + beans[i].isRecording()); } result = beans; } } return (result); } /** * {@inheritDoc} */ public Recorder getRecorderByDevice(String s) { Recorder result = null; ArrayList<Recorder> l = getRecorderList(); if ((l != null) && (s != null)) { LogUtil.log(LogUtil.DEBUG, "getRecorderByDevice: <" + s + ">"); LogUtil.log(LogUtil.DEBUG, "getRecorderByDevice: " + l.size()); for (int i = 0; i < l.size(); i++) { Recorder tmp = l.get(i); LogUtil.log(LogUtil.DEBUG, "getRecorderByDevice: <" + tmp.getDevice() + ">"); if (s.equals(tmp.getDevice())) { result = tmp; break; } } } return (result); } /** * {@inheritDoc} */ public ProgramData[] getProgramData() { ProgramData[] result = null; ArrayList<ProgramData> l = getProgramDataList(); if ((l != null) && (l.size() > 0)) { result = l.toArray(new ProgramData[l.size()]); } return (result); } /** * {@inheritDoc} */ public boolean hasProgramData() { return (getProgramData() != null); } /** * {@inheritDoc} */ public boolean isProgramDataUpdatingNow() { boolean result = false; ProgramData[] array = getProgramData(); if ((array != null) && (array.length > 0)) { result = array[0].isUpdatingNow(); } return (result); } /** * {@inheritDoc} */ public long getProgramDataNextTimeToRun() { long result = -1; ProgramData[] array = getProgramData(); if ((array != null) && (array.length > 0)) { result = array[0].getNextTimeToRun(); } return (result); } /** * {@inheritDoc} */ public boolean requestProgramDataUpdate() { boolean result = false; ProgramData[] array = getProgramData(); if ((array != null) && (array.length > 0)) { for (int i = 0; i < array.length; i++) { boolean willdo = array[i].requestUpdate(); if (willdo) { result = true; } } } return (result); } /** * {@inheritDoc} */ public String getHost() { return (host); } /** * Convenience method to set this property. * * @param s The given host value. */ public void setHost(String s) { host = s; } /** * {@inheritDoc} */ public int getPort() { return (port); } /** * Convenience method to set this property. * * @param i The given port value. */ public void setPort(int i) { port = i; } /** * {@inheritDoc} */ public int getHttpPort() { return (httpPort); } /** * Convenience method to set this property. * * @param i The given http port value. */ public void setHttpPort(int i) { httpPort = i; } /** * {@inheritDoc} */ public String[] getTrailerURLs() { String[] result = null; String thome = getTrailerHome(); String tintro = getTrailerIntro(); if ((thome != null) && (tintro != null)) { File dir = new File(thome); File[] all = dir.listFiles(); if ((all != null) && (all.length > 0)) { Arrays.sort(all, new FileSort()); result = new String[all.length + 1]; result[0] = computeStreamURL(tintro); for (int i = 1; i < result.length; i++) { result[i] = computeStreamURL(all[i - 1].getPath()); } } } return (result); } /** * {@inheritDoc} */ public String getTrailerHome() { return (getConfiguredTrailerHome()); } /** * {@inheritDoc} */ public String getTrailerIntro() { return (getConfiguredTrailerIntro()); } /** * {@inheritDoc} */ public String getFeatureIntro169() { return (getConfiguredFeatureIntro169()); } /** * {@inheritDoc} */ public String getFeatureIntro235() { return (getConfiguredFeatureIntro235()); } /** * {@inheritDoc} */ public String getFeatureIntro43() { return (getConfiguredFeatureIntro43()); } /** * {@inheritDoc} */ public String getGroupName() { return (getConfiguredGroupName()); } /** * {@inheritDoc} */ public String[] getStreamPaths() { return (getConfiguredStreamPaths()); } /** * {@inheritDoc} */ public String getDocumentRoot() { return (getConfiguredDocumentRoot()); } /** * {@inheritDoc} */ public int getStreamPort() { return (getConfiguredStreamPort()); } /** * {@inheritDoc} */ public Configuration getConfigurationBySource(String s) { Configuration result = null; Configuration[] array = getConfigurations(); if ((s != null) && (array != null)) { for (int i = 0; i < array.length; i++) { if (array[i].isSource(s)) { result = array[i]; break; } } } return (result); } /** * Convenience method to get the configured value of IMAGE_HOME, the * directory where metadata images will be stored. * * @return A String object. */ public String getConfiguredImageHome() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.IMAGE_HOME); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of TRAILER_HOME, the * directory where downloaded trailers will be stored. * * @return A String object. */ public String getConfiguredTrailerHome() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.TRAILER_HOME); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of TRAILER_INTRO, the * file that is an intro to the trailers. * * @return A String object. */ public String getConfiguredTrailerIntro() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.TRAILER_INTRO); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of FEATURE_INTRO_169, * the file that is an intro to a feature in 16:9 aspect ratio. * * @return A String object. */ public String getConfiguredFeatureIntro169() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.FEATURE_INTRO_169); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of FEATURE_INTRO_235, * the file that is an intro to a feature in 2.35:1 aspect ratio. * * @return A String object. */ public String getConfiguredFeatureIntro235() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.FEATURE_INTRO_235); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of FEATURE_INTRO_43, * the file that is an intro to a feature in 4:3 aspect ratio. * * @return A String object. */ public String getConfiguredFeatureIntro43() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.FEATURE_INTRO_43); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of GROUP_NAME. * * @return A String object. */ public String getConfiguredGroupName() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.GROUP_NAME); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of STREAM_PORT. * * @return An int value. */ public int getConfiguredStreamPort() { int result = 80; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.STREAM_PORT); if (nv != null) { result = Util.str2int(nv.getValue(), result); } } return (result); } /** * Convenience method to get the configured value of HTTP_DOCUMENT_ROOT. * * @return A String object. */ public String getConfiguredDocumentRoot() { String result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.HTTP_DOCUMENT_ROOT); if (nv != null) { result = nv.getValue(); } } return (result); } /** * Convenience method to get the configured value of STREAM_PATHS. * * @return A String array. */ public String[] getConfiguredStreamPaths() { String[] result = null; Configuration c = getConfiguration(); if (c != null) { NameValue nv = c.findNameValueByName(NMSConstants.STREAM_PATHS); if (nv != null) { result = nv.valueToArray(); } } return (result); } /** * {@inheritDoc} */ public Channel[] getChannels() { Channel[] result = null; ProgramData[] all = getProgramData(); if ((all != null) && (all.length > 0)) { result = all[0].getChannels(); updateChannelLogoURL(result); } return (result); } /** * {@inheritDoc} */ public Channel[] getRecordableChannels() { Channel[] result = null; Scheduler s = getScheduler(); if (s != null) { result = s.getRecordableChannels(); updateChannelLogoURL(result); } return (result); } /** * {@inheritDoc} */ public Airing[] getAiringsByChannel(Channel c) { Airing[] result = null; ProgramData[] all = getProgramData(); if ((c != null) && (all != null) && (all.length > 0)) { result = all[0].getAiringsByChannel(c); } return (result); } /** * {@inheritDoc} */ public ShowAiring[] getShowAiringsByChannel(Channel c) { ShowAiring[] result = null; ArrayList<ShowAiring> list = getShowAiringListByChannel(c); if (list == null) { ProgramData[] array = getProgramData(); if ((array != null) && (c != null)) { list = new ArrayList<ShowAiring>(); for (int i = 0; i < array.length; i++) { Airing[] airs = array[i].getAiringsByChannel(c); if (airs != null) { String hp = getHost() + ":" + getPort(); for (int j = 0; j < airs.length; j++) { Show show = array[i].getShowByAiring(airs[j]); if (show != null) { ShowAiring sa = new ShowAiring(show, airs[j]); sa.setHostPort(hp); list.add(sa); } } } } if (list.size() > 0) { addShowAiringListByChannel(c, list); } } } if ((list != null) && (list.size() > 0)) { Collections.sort(list); long now = System.currentTimeMillis(); int count = 0; for (int i = 0; i < list.size(); i++) { Airing a = list.get(i).getAiring(); if (a != null) { Date d = a.getAirDate(); if (d != null) { if (d.getTime() > now) { break; } else { count++; } } else { count++; } } else { count++; } } count--; for (int i = 0; i < count; i++) { list.remove(0); } result = list.toArray(new ShowAiring[list.size()]); } return (result); } /** * {@inheritDoc} */ public ShowAiring[] getShowAiringsByChannelAndSeriesId(Channel c, String seriesId) { ShowAiring[] result = null; ProgramData[] array = getProgramData(); if (array != null) { for (int i = 0; i < array.length; i++) { result = array[i].getShowAiringsByChannelAndSeriesId(c, seriesId); if (result != null) { Arrays.sort(result); String hp = getHost() + ":" + getPort(); for (int j = 0; j < result.length; j++) { result[j].setHostPort(hp); } break; } } } return (result); } /** * {@inheritDoc} */ public ShowAiring[] getShowAirings(String pattern, int searchType) { ShowAiring[] result = null; ProgramData[] array = getProgramData(); Channel[] chans = getRecordableChannels(); if ((array != null) && (chans != null)) { Arrays.sort(chans); for (int i = 0; i < array.length; i++) { result = array[i].getShowAirings(pattern, searchType); if (result != null) { result = substituteFromCache(result, chans); Arrays.sort(result); String hp = getHost() + ":" + getPort(); for (int j = 0; j < result.length; j++) { result[j].setHostPort(hp); } break; } } } return (result); } /** * {@inheritDoc} */ public Channel[] getChannelsByListingName(String s) { Channel[] result = null; ProgramData[] array = getProgramData(); if ((array != null) && (s != null)) { for (int i = 0; i < array.length; i++) { Listing listing = array[i].getListingByName(s); if (listing != null) { result = array[i].getChannelsByListing(listing); if (result != null) { updateChannelLogoURL(result); break; } } } } return (result); } /** * {@inheritDoc} */ public Channel getChannelById(int id, String lid) { Channel result = null; ProgramData[] array = getProgramData(); if (array != null) { for (int i = 0; i < array.length; i++) { result = array[i].getChannelById(id, lid); if (result != null) { updateChannelLogoURL(result); break; } } } return (result); } /** * {@inheritDoc} */ public Show getShowById(String id) { Show result = null; ProgramData[] array = getProgramData(); if ((array != null) && (id != null)) { for (int i = 0; i < array.length; i++) { result = array[i].getShowById(id); if (result != null) { break; } } } return (result); } private ShowAiring[] substituteFromCache(ShowAiring[] array, Channel[] chans) { ShowAiring[] result = array; if ((array != null) && (array.length > 0)) { ArrayList<ShowAiring> l = new ArrayList<ShowAiring>(); for (int i = 0; i < result.length; i++) { ShowAiring sa = substituteFromCache(array[i], chans); if (sa != null) { l.add(sa); } } if (l.size() > 0) { result = l.toArray(new ShowAiring[l.size()]); } } return (result); } private ShowAiring substituteFromCache(ShowAiring sa, Channel[] chans) { ShowAiring result = null; if ((sa != null) && (chans != null)) { Airing a = sa.getAiring(); if (a != null) { Channel c = getChannelById(a.getChannelId(), a.getListingId()); if ((c != null) && (Arrays.binarySearch(chans, c) >= 0)) { ShowAiring[] array = getShowAiringsByChannel(c); if (array != null) { for (int i = 0; i < array.length; i++) { if (a.equals(array[i].getAiring())) { result = array[i]; break; } } } } } } return (result); } private Task[] reconcile(Task[] array) { Task[] result = null; if (array != null) { for (int i = 0; i < array.length; i++) { String mytitle = array[i].getTitle(); if (mytitle != null) { if (mytitle.startsWith("Comskip")) { array[i].setSelectable(true); } } } result = Arrays.copyOf(array, array.length); } return (result); } /** * {@inheritDoc} */ public RecordingRule[] getRecordingRules() { RecordingRule[] result = null; Scheduler s = getScheduler(); if (s != null) { result = s.getRecordingRules(); if ((result != null) && (result.length > 0)) { String h = getHost(); int p = getHttpPort(); String hp = h + ":" + getPort(); for (int i = 0; i < result.length; i++) { result[i].setHostPort(hp); String top = "http://" + h + ":" + p + "/" + NMSConstants.HTTP_IMAGES_NAME + "/"; String sid = result[i].getSeriesId(); if (sid != null) { result[i].setBannerURL(top + sid + "_banner.jpg"); result[i].setPosterURL(top + sid + "_poster.jpg"); result[i].setFanartURL(top + sid + "_fanart.jpg"); } // We should sync up the PostProc Workers with the // lightweight task instances here so the user gets // the most recent info. But we won't delete old // workers in case it is just temporarily not deployed. /* Task[] update = reconcile(result[i].getTasks()); if (update != null) { result[i].setTasks(update); s.addRecordingRule(result[i]); } */ } } } return (result); } /** * {@inheritDoc} */ public Recording getRecordingById(String id) { Recording result = null; Recording[] array = getRecordings(); if ((id != null) && (array != null)) { for (int i = 0; i < array.length; i++) { if (id.equals(array[i].getId())) { result = array[i]; result.setHostPort(getHost() + ":" + getPort()); break; } } } return (result); } /** * {@inheritDoc} */ public Recording[] getRecordings() { Recording[] result = null; Scheduler s = getScheduler(); LogUtil.log(LogUtil.DEBUG, "getRecordings: scheduler <" + s + ">"); if (s != null) { result = s.getRecordings(); LogUtil.log(LogUtil.DEBUG, "getRecordings: result from scheduler <" + result + ">"); // We should update the image URLs for the client. Persisting // the URLs is not a good idea because the URL could change. // Either by config the port changes or less likely the IP // changes. Either way we will update them. We don't check // if they actually exist, we will just build them by rule. if (result != null) { String h = getHost(); int p = getHttpPort(); if (h != null) { String hp = h + ":" + port; String top = "http://" + h + ":" + p + "/" + NMSConstants.HTTP_IMAGES_NAME + "/"; for (int i = 0; i < result.length; i++) { String sid = result[i].getSeriesId(); if (sid != null) { result[i].setBannerURL(top + sid + "_banner.jpg"); result[i].setPosterURL(top + sid + "_poster.jpg"); result[i].setFanartURL(top + sid + "_fanart.jpg"); } result[i].setHostPort(hp); result[i].setStreamURL(computeStreamURL(result[i])); } } } } return (result); } private String computeStreamURL(String path) { String result = null; String h = getHost(); int streamport = getStreamPort(); String[] array = getConfiguredStreamPaths(); if ((h != null) && (array != null) && (path != null)) { boolean found = false; path = path.replace("\\", "/"); for (int i = 0; i < array.length; i++) { if (path.startsWith(array[i])) { path = path.substring(array[i].length()); found = true; break; } } if ((found) && (path != null)) { if (path.startsWith("/")) { result = "http://" + h + ":" + streamport + path; } else { result = "http://" + h + ":" + streamport + "/" + path; } } } return (result); } private String computeStreamURL(Photo p) { String result = null; String h = getHost(); int streamport = getStreamPort(); String[] array = getConfiguredStreamPaths(); if ((h != null) && (array != null) && (p != null)) { boolean found = false; String path = p.getPath(); if (path != null) { path = path.replace("\\", "/"); for (int i = 0; i < array.length; i++) { if (path.startsWith(array[i])) { path = path.substring(array[i].length()); found = true; break; } } } if ((found) && (path != null)) { if (path.startsWith("/")) { result = "http://" + h + ":" + streamport + path; } else { result = "http://" + h + ":" + streamport + "/" + path; } } } return (result); } private String computeStreamURL(LiveTV l) { String result = null; String h = getHost(); int streamport = getStreamPort(); String[] array = getConfiguredStreamPaths(); if ((h != null) && (array != null) && (l != null)) { boolean found = false; String path = l.getPath(); if (path != null) { path = path.replace("\\", "/"); for (int i = 0; i < array.length; i++) { if (path.startsWith(array[i])) { path = path.substring(array[i].length()); found = true; break; } } } if ((found) && (path != null)) { if (path.startsWith("/")) { result = "http://" + h + ":" + streamport + path; } else { result = "http://" + h + ":" + streamport + "/" + path; } } } return (result); } private String computeStreamURL(Recording r) { String result = null; String h = getHost(); int streamport = getStreamPort(); if ((h != null) && (r != null)) { // We have a recording that is finished, we will let // apache serve it up. String[] array = getConfiguredStreamPaths(); if (array != null) { String path = r.getPath(); if (path != null) { String iext = r.getIndexedExtension(); // First see if we have an mp4 file. File mp4tmp = new File(path + ".mp4"); if (mp4tmp.exists()) { // We do so override the extension in the DB. // We are doing this because we are in the process // of going h264/mp4 exclusively and we can update // old recordings when we have a chance. Yeah this // is hackish. iext = "mp4"; r.setIndexedExtension(iext); } if ((iext != null) && (iext.length() > 0)) { File tmp = new File(path + "." + iext); if (tmp.exists()) { path = tmp.getPath(); } } else { String trunk = path.substring(0, path.lastIndexOf(".")); File tmp = new File(trunk + ".m3u8"); if (tmp.exists()) { path = tmp.getPath(); } } } boolean found = false; if (path != null) { path = path.replace("\\", "/"); for (int i = 0; i < array.length; i++) { if (path.startsWith(array[i])) { path = path.substring(array[i].length()); found = true; break; } } } if ((found) && (path != null)) { if (path.startsWith("/")) { result = "http://" + h + ":" + streamport + path; } else { result = "http://" + h + ":" + streamport + "/" + path; } } } } return (result); } /** * Really remove the recording files. * * @param r The Recording to remove. */ public void performRemoval(Recording r) { LogUtil.log(LogUtil.DEBUG, "Recording to physically remove: <" + r + ">"); if (r != null) { String path = r.getPath(); if (path != null) { File file = new File(path); String iext = r.getIndexedExtension(); // Of course delete the file. if (!file.delete()) { LogUtil.log(LogUtil.WARNING, file.getPath() + " delete fail"); } // The screenshot is a "filename.png" file. File pngfile = new File(file.getPath() + ".png"); if (!pngfile.delete()) { LogUtil.log(LogUtil.WARNING, pngfile.getPath() + " del fail"); } // The index file is "filename.iext". if (iext != null) { File iextfile = new File(file.getPath() + "." + iext); if (!iextfile.delete()) { LogUtil.log(LogUtil.WARNING, iextfile.getPath() + " del fail"); } } // Other recorders or processes might add other files // with the rule of a different extension. Let's find // them and delete them. File parent = file.getParentFile(); String fname = file.getName(); if ((parent != null) && (fname != null)) { // This really should get everything as it // includes the show ID and time up to the // minute. fname = fname.substring(0, fname.lastIndexOf("_")); File[] array = parent.listFiles(new StartsWithFilter(fname)); if (array != null) { for (int i = 0; i < array.length; i++) { if (!array[i].delete()) { LogUtil.log(LogUtil.WARNING, array[i].getPath() + " del fail"); } } } } } } } /** * {@inheritDoc} */ public void removeRecording(Recording r, boolean allowRerecord) { LogUtil.log(LogUtil.DEBUG, "removeRecording: allowRerecord: " + allowRerecord); Scheduler s = getScheduler(); if ((s != null) && (r != null)) { // Clients can muck with the properties of a Recording. We // need to have an instance that is meaningful to us so lets // look it up by Id. r = getRecordingById(r.getId()); s.removeRecording(r); if (allowRerecord) { s.removeRecordedShow(new RecordedShow(r.getShowId())); s.requestRescheduling(); } ArrayList<Recording> l = getRemoveRecordingList(); if (l != null) { synchronized (l) { LogUtil.log(LogUtil.DEBUG, "Adding Recording to remove when we are " + "not busy. <" + r + ">"); l.add(r); } } /* String path = r.getPath(); if (path != null) { final File file = new File(path); final String iext = r.getIndexedExtension(); ActionListener taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { // Of course delete the file. if (!file.delete()) { LogUtil.log(LogUtil.WARNING, file.getPath() + " delete fail"); } // The screenshot is a "filename.png" file. File pngfile = new File(file.getPath() + ".png"); if (!pngfile.delete()) { LogUtil.log(LogUtil.WARNING, pngfile.getPath() + " del fail"); } // The index file is "filename.iext". if (iext != null) { File iextfile = new File(file.getPath() + "." + iext); if (!iextfile.delete()) { LogUtil.log(LogUtil.WARNING, iextfile.getPath() + " del fail"); } } // Other recorders or processes might add other files // with the rule of a different extension. Let's find // them and delete them. File parent = file.getParentFile(); String fname = file.getName(); if ((parent != null) && (fname != null)) { // This really should get everything as it // includes the show ID and time up to the // minute. fname = fname.substring(0, fname.lastIndexOf("_")); File[] array = parent.listFiles(new StartsWithFilter(fname)); if (array != null) { for (int i = 0; i < array.length; i++) { if (!array[i].delete()) { LogUtil.log(LogUtil.WARNING, array[i].getPath() + " del fail"); } } } } } }; Timer timer = new Timer(1000, taskPerformer); timer.setRepeats(false); timer.start(); } */ sendMessage(NMSConstants.MESSAGE_RECORDING_REMOVED); } } /** * {@inheritDoc} */ public void stopRecording(Recording r) { LogUtil.log(LogUtil.INFO, "stopRecording <" + r + ">"); Scheduler s = getScheduler(); if ((s != null) && (r != null)) { // Clients can muck with the properties of a Recording. We // need to have an instance that is meaningful to us so lets // look it up by Id. r = getRecordingById(r.getId()); boolean found = false; Recorder[] array = s.getConfiguredRecorders(); if ((array != null) && (r != null)) { for (int i = 0; i < array.length; i++) { if (array[i].isRecording(r)) { LogUtil.log(LogUtil.DEBUG, "Stopping <" + array[i] + ">"); array[i].stopRecording(); found = true; break; } } } // Now if we didn't find the Recorder, we may be in a funky // mode. So let's be trustful and flag the recording as stopped. if (!found) { r.setCurrentlyRecording(false); long now = System.currentTimeMillis(); r.setDuration((now - r.getRealStart()) / 1000L); s.updateRecording(r); } } } /** * {@inheritDoc} */ public Upcoming[] getUpcomings() { Upcoming[] result = null; Scheduler s = getScheduler(); if (s != null) { result = s.getUpcomings(); // We should update the image URLs for the client. Persisting // the URLs is not a good idea because the URL could change. // Either by config the port changes or less likely the IP // changes. Either way we will update them. We don't check // if they actually exist, we will just build them by rule. if (result != null) { String h = getHost(); int p = getHttpPort(); if (h != null) { String hp = h + ":" + port; String top = "http://" + h + ":" + p + "/" + NMSConstants.HTTP_IMAGES_NAME + "/"; for (int i = 0; i < result.length; i++) { String sid = result[i].getSeriesId(); if (sid != null) { result[i].setBannerURL(top + sid + "_banner.jpg"); result[i].setPosterURL(top + sid + "_poster.jpg"); result[i].setFanartURL(top + sid + "_fanart.jpg"); } result[i].setHostPort(hp); } } } } return (result); } /** * {@inheritDoc} */ public void overrideUpcoming(Upcoming u) { Scheduler s = getScheduler(); if ((u != null) && (s != null)) { String sid = u.getShowId(); if (sid != null) { RecordedShow rs = new RecordedShow(sid); if (NMSConstants.PREVIOUSLY_RECORDED.equals(u.getStatus())) { // This means we want to forget the old recording. s.removeRecordedShow(rs); } else { // Anything here means pretend we already recorded it. s.addRecordedShow(rs); } s.requestRescheduling(); } } } /** * {@inheritDoc} */ public void save(int imageType, byte[] data, String id) { if ((data != null) && (id != null)) { String imageHome = getConfiguredImageHome(); if (imageHome == null) { imageHome = "."; } String name = null; String rokusdname = null; String rokuhdname = null; switch (imageType) { default: case NMSConstants.BANNER_IMAGE_TYPE: name = imageHome + "/" + id + "_banner.jpg"; break; case NMSConstants.FANART_IMAGE_TYPE: name = imageHome + "/" + id + "_fanart.jpg"; break; case NMSConstants.POSTER_IMAGE_TYPE: name = imageHome + "/" + id + "_poster.jpg"; break; } try { ByteArrayInputStream bais = new ByteArrayInputStream(data); BufferedImage bi = ImageIO.read(bais); if (bi != null) { ImageIO.write(bi, "jpg", new File(name)); if (rokuhdname != null) { BufferedImage hd = createImage(bi, 388); hd = hd.getSubimage(49, 0, 290, 218); ImageIO.write(hd, "jpg", new File(rokuhdname)); BufferedImage sd = createImage(bi, 256); sd = sd.getSubimage(21, 0, 214, 144); ImageIO.write(sd, "jpg", new File(rokusdname)); } } else { LogUtil.log(LogUtil.WARNING, "can't load <" + data + ">"); } } catch (IOException ex) { LogUtil.log(LogUtil.WARNING, "save image: " + ex.getMessage()); } } } /** * {@inheritDoc} */ public void save(int imageType, String url, String id) { if ((url != null) && (id != null)) { String imageHome = getConfiguredImageHome(); if (imageHome == null) { imageHome = "."; } String name = null; String rokusdname = null; String rokuhdname = null; switch (imageType) { default: case NMSConstants.BANNER_IMAGE_TYPE: name = imageHome + "/" + id + "_banner.jpg"; break; case NMSConstants.FANART_IMAGE_TYPE: name = imageHome + "/" + id + "_fanart.jpg"; break; case NMSConstants.POSTER_IMAGE_TYPE: name = imageHome + "/" + id + "_poster.jpg"; break; } try { BufferedImage bi = ImageIO.read(new URL(url)); if (bi != null) { ImageIO.write(bi, "jpg", new File(name)); if (rokuhdname != null) { BufferedImage hd = createImage(bi, 388); hd = hd.getSubimage(49, 0, 290, 218); ImageIO.write(hd, "jpg", new File(rokuhdname)); BufferedImage sd = createImage(bi, 256); sd = sd.getSubimage(21, 0, 214, 144); ImageIO.write(sd, "jpg", new File(rokusdname)); } } else { LogUtil.log(LogUtil.WARNING, "can't load <" + url + ">"); } } catch (IOException ex) { LogUtil.log(LogUtil.WARNING, "save image: " + ex.getMessage()); } } } private BufferedImage createImage(BufferedImage bi, int scalex) { BufferedImage result = null; if (bi != null) { Image scaled = bi.getScaledInstance(388, -1, Image.SCALE_DEFAULT); if (scaled instanceof BufferedImage) { LogUtil.log(LogUtil.INFO, "It's a BufferedImage already..."); result = (BufferedImage) scaled; } else { LogUtil.log(LogUtil.INFO, "Have to Make a BufferedImage!"); result = new BufferedImage(scaled.getWidth(null), scaled.getHeight(null), bi.getType()); Graphics2D g2d = result.createGraphics(); g2d.drawImage(scaled, 0, 0, null); } } return (result); } /** * {@inheritDoc} */ public void schedule(RecordingRule rr) { Scheduler s = getScheduler(); if ((s != null) && (rr != null)) { if (rr.getType() != RecordingRule.DO_NOT_RECORD_TYPE) { s.addRecordingRule(rr); } else { s.removeRecordingRule(rr); } s.requestRescheduling(); sendMessage(NMSConstants.MESSAGE_RULE_UPDATE); } } /** * The EventSender instance allows implementations to send messages * via the EventAdmin. * * @return An EventSender instance. */ public EventSender getEventSender() { return (eventSender); } /** * The EventSender instance allows implementations to send messages * via the EventAdmin. * * @param es An EventSender instance. */ public void setEventSender(EventSender es) { eventSender = es; } /** * {@inheritDoc} */ public void sendMessage(String s) { EventSender es = getEventSender(); if ((s != null) && (es != null)) { es.sendMessage(s); } } /** * {@inheritDoc} */ public void dataUpdate(DataUpdateEvent event) { // Let's clear out our cache of ShowAirings per Channel since // we have fresh guide data. clearShowAiringCacheMap(); Scheduler s = getScheduler(); if (s != null) { s.rebuildCache(); s.requestRescheduling(); Channel[] all = getRecordableChannels(); if ((all != null) && (all.length > 0)) { for (int i = 0; i < all.length; i++) { ShowAiring[] sas = getShowAiringsByChannel(all[i]); LogUtil.log(LogUtil.DEBUG, "Cached ShowAirings for: " + all[i]); } } } // Also a good time to cache the channel logos. ProgramData[] pds = getProgramData(); if ((pds != null) && (pds.length > 0)) { String imageHome = getConfiguredImageHome(); if (imageHome == null) { imageHome = "."; } File imageHomeFile = new File(imageHome); for (int i = 0; i < pds.length; i++) { ChannelLogo[] clogos = pds[i].getChannelLogos(); if ((clogos != null) && (clogos.length > 0)) { for (int j = 0; j < clogos.length; j++) { int cid = clogos[j].getChannelId(); String url = clogos[j].getUrl(); String md5 = clogos[j].getMd5(); if ((url != null) && (md5 != null)) { int index = url.lastIndexOf("."); if (index != -1) { String ext = url.substring(index + 1); File logo = new File(imageHomeFile, "logo_" + cid + "_" + md5 + "." + ext); if (!logo.exists()) { // Need to fetch it. try { URL iurl = new URL(url); BufferedImage bi = ImageIO.read(iurl); ImageIO.write(bi, ext, logo); File logoCopy = new File(imageHomeFile, "logo_" + cid + "." + ext); ImageIO.write(bi, ext, logoCopy); LogUtil.log(LogUtil.DEBUG, "wrote logo: " + logo.getPath()); LogUtil.log(LogUtil.DEBUG, "wrote logoCopy: " + logoCopy.getPath()); } catch (Exception ex) { LogUtil.log(LogUtil.WARNING, "Unable to save logo: " + ex.getMessage()); } } } } } } } } } /** * {@inheritDoc} */ public LiveTV openSession() { LiveTV result = null; Live lve = getLive(); if (lve != null) { result = lve.openSession(); if (result != null) { result.setHostPort(getHost() + ":" + getPort()); result.setStreamURL(computeStreamURL(result)); LogUtil.log(LogUtil.DEBUG, "STREAM URL SET TO: " + result.getStreamURL()); } } return (result); } /** * {@inheritDoc} */ public LiveTV openSession(String channelNumber) { LiveTV result = null; Live lve = getLive(); if (lve != null) { result = lve.openSession(channelNumber); if (result != null) { result.setHostPort(getHost() + ":" + getPort()); result.setStreamURL(computeStreamURL(result)); LogUtil.log(LogUtil.DEBUG, "STREAM URL SET TO: " + result.getStreamURL()); } } return (result); } /** * {@inheritDoc} */ public LiveTV openSession(String host, int port) { LiveTV result = null; Live lve = getLive(); if (lve != null) { LogUtil.log(LogUtil.DEBUG, "request Host " + host); LogUtil.log(LogUtil.DEBUG, "request Port " + port); result = lve.openSession(host, port); if (result != null) { result.setHostPort(getHost() + ":" + getPort()); LogUtil.log(LogUtil.DEBUG, "DestinationHost " + result.getDestinationHost()); LogUtil.log(LogUtil.DEBUG, "DestinationPort " + result.getDestinationPort()); } } return (result); } /** * {@inheritDoc} */ public LiveTV openSession(String host, int port, String channelNumber) { LiveTV result = null; Live lve = getLive(); if (lve != null) { LogUtil.log(LogUtil.DEBUG, "request Host " + host); LogUtil.log(LogUtil.DEBUG, "request Port " + port); result = lve.openSession(host, port, channelNumber); if (result != null) { result.setHostPort(getHost() + ":" + getPort()); LogUtil.log(LogUtil.DEBUG, "DestinationHost " + result.getDestinationHost()); LogUtil.log(LogUtil.DEBUG, "DestinationPort " + result.getDestinationPort()); } } return (result); } /** * {@inheritDoc} */ public LiveTV changeChannel(LiveTV l, Channel c) { Live lve = getLive(); if (lve != null) { lve.changeChannel(l, c); l.setStreamURL(computeStreamURL(l)); } return (l); } /** * {@inheritDoc} */ public void closeSession(LiveTV l) { Live lve = getLive(); if (lve != null) { lve.closeSession(l); } } private OnDemand getOnDemandByName(String name) { OnDemand result = null; if (name != null) { OnDemand[] array = getOnDemands(); if (array != null) { for (int i = 0; i < array.length; i++) { if (name.equals(array[i].getTitle())) { result = array[i]; break; } } } } return (result); } /** * {@inheritDoc} */ public String[] getOnDemandNames() { String[] result = null; return (result); } /** * {@inheritDoc} */ public StreamSession openSession(String name, String host, int port) { StreamSession result = null; if ((name != null) && (host != null)) { OnDemand od = getOnDemandByName(name); if (od != null) { result = od.openSession(host, port); } } else { LogUtil.log(LogUtil.WARNING, "Trying to do OnDemand from wrong NMS"); } return (result); } /** * {@inheritDoc} */ public void command(StreamSession ss, int type) { if (ss != null) { String hp = ss.getHostPort(); if (hp.equals(getHost() + ":" + getPort())) { OnDemand od = getOnDemandByName(ss.getName()); if (od != null) { od.command(ss, type); } } } } /** * {@inheritDoc} */ public void closeSession(StreamSession ss) { if (ss != null) { String hp = ss.getHostPort(); if (hp.equals(getHost() + ":" + getPort())) { OnDemand od = getOnDemandByName(ss.getName()); if (od != null) { od.closeSession(ss); } } } } /** * {@inheritDoc} */ public Tag getRootTag() { Tag result = null; PhotoManager pm = getPhotoManager(); if (pm != null) { result = pm.getRootTag(); } return (result); } /** * {@inheritDoc} */ public Photo[] getPhotos() { Photo[] result = null; PhotoManager pm = getPhotoManager(); if (pm != null) { result = pm.getPhotos(); if ((result != null) && (result.length > 0)) { for (int i = 0; i < result.length; i++) { String url = computeStreamURL(result[i]); if (url != null) { result[i].setPath(url); } } } } return (result); } /** * {@inheritDoc} */ public void photoScan() { PhotoManager pm = getPhotoManager(); if (pm != null) { pm.photoScan(); } } /** * {@inheritDoc} */ public void save(Video v) { VideoManager vm = getVideoManager(); if ((vm != null) && (v != null)) { vm.save(v); } } /** * {@inheritDoc} */ public Video getVideoById(String id) { Video result = null; VideoManager vm = getVideoManager(); if ((vm != null) && (id != null)) { result = vm.getVideoById(id); } return (result); } /** * {@inheritDoc} */ public Video[] getVideos() { Video[] result = null; VideoManager vm = getVideoManager(); if (vm != null) { result = vm.getVideos(); // Let's eliminate the hidden. if ((result != null) && (result.length > 0)) { boolean found = false; ArrayList<Video> list = new ArrayList<Video>(); for (int i = 0; i < result.length; i++) { if (!result[i].isHidden()) { list.add(result[i]); } else { found = true; } } if (found) { result = list.toArray(new Video[list.size()]); } } } return (result); } /** * {@inheritDoc} */ public void removeVideo(Video v) { VideoManager vm = getVideoManager(); if ((vm != null) && (v != null)) { vm.removeVideo(v); } } /** * {@inheritDoc} */ public void videoScan() { VideoManager vm = getVideoManager(); if (vm != null) { vm.videoScan(); } } /** * {@inheritDoc} */ public void generateArtwork(Video v, int seconds) { VideoManager vm = getVideoManager(); if (vm != null) { vm.generateArtwork(v, seconds); } } /** * {@inheritDoc} */ public boolean performChannelScan(String recorderSource, String type) { boolean result = false; LogUtil.log(LogUtil.DEBUG, "performChannelScan using <" + recorderSource + ">"); if (recorderSource != null) { int index = recorderSource.indexOf(" "); if (index != -1) { String device = recorderSource.substring(index); device = device.trim(); LogUtil.log(LogUtil.DEBUG, "parse device <" + device + ">"); Recorder[] array = getRecorders(); if ((array != null) && (array.length > 0)) { LogUtil.log(LogUtil.DEBUG, "recorder count " + array.length); Recorder r = null; for (int i = 0; i < array.length; i++) { LogUtil.log(LogUtil.DEBUG, "rec dev: <" + array[i].getDevice() + ">"); if (device.equals(array[i].getDevice())) { r = array[i]; break; } } Scheduler s = getScheduler(); if ((s != null) && (r != null) && (r.supportsScan())) { String ln = s.getListingNameByRecorder(r); if (ln != null) { Channel[] chans = getChannelsByListingName(ln); chans = r.getCustomChannels(chans); if (chans != null) { result = true; r.performScan(chans, type); } } } } } } return (result); } /** * {@inheritDoc} */ public State getState() { return (new State(this)); } /** * {@inheritDoc} */ public boolean supportsLiveTV() { return (getLive() != null); } /** * {@inheritDoc} */ public boolean supportsOnDemand() { return (getOnDemands() != null); } /** * {@inheritDoc} */ public boolean supportsOnDemand(String name) { boolean result = false; if ((name != null) && (supportsOnDemand())) { OnDemand[] array = getOnDemands(); for (int i = 0; i < array.length; i++) { if (name.equals(array[i].getTitle())) { result = true; break; } } } return (result); } private void updateChannelLogoURL(Channel[] array) { if ((array != null) && (array.length > 0)) { for (int i = 0; i < array.length; i++) { updateChannelLogoURL(array[i]); } } } private void updateChannelLogoURL(Channel c) { if (c != null) { int cid = c.getId(); String h = getHost(); int p = getHttpPort(); String ihome = getConfiguredImageHome(); if (ihome == null) { ihome = ""; } if (h != null) { String hp = h + ":" + port; String top = "http://" + h + ":" + p + "/" + NMSConstants.HTTP_IMAGES_NAME + "/"; String[] exts = { "png", "jpg" }; for (int i = 0; i < exts.length; i++) { File logo = new File(ihome + "/logo_" + cid + "." + exts[i]); if (logo.exists()) { c.setLogoURL(top + "logo_" + cid + "." + exts[i]); break; } } } } } /** * Override and use the title property. * * @return The title property. */ public String toString() { return (getTitle()); } static class RecorderSortByTitleDevice implements Comparator<Recorder>, Serializable { public int compare(Recorder r0, Recorder r1) { String r0str = r0.getTitle() + " " + r0.getDevice(); String r1str = r1.getTitle() + " " + r1.getDevice(); return (r0str.compareTo(r1str)); } } static class FileSort implements Comparator<File>, Serializable { public int compare(File f0, File f1) { Long l0 = Long.valueOf(f0.lastModified()); Long l1 = Long.valueOf(f1.lastModified()); return (l1.compareTo(l0)); } } }