Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.vestel.android.tvframework.gracenote;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.media.tv.TvContract;
- import android.net.Uri;
- import android.os.AsyncTask;
- import android.util.Log;
- import com.vestel.android.tvframework.epg.EventInformation;
- import com.vestel.android.tvframework.gracenote.Cache.ImageCache;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSAiring;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSChannel;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSChannelArray;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSChannelFromSatellite;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSContributer;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSGNBase;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSProgram;
- import com.vestel.android.tvframework.gracenote.GracenoteImpl.VSSeries;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.concurrent.CopyOnWriteArrayList;
- public final class GraceNoteWrapper {
- private static class SingletonHolder {
- static final GraceNoteWrapper mInstance = new GraceNoteWrapper();
- }
- private static final int RAM_CACHE_SIZE = 256 * 1024;//256Kb;
- private Long mLastStartTime = 0L;
- private Long mLastEndTime = 0L;
- private VSChannel previousChannel = null;
- protected ImageCache mCache = null;
- // ChannelArray is our main entry point into GraceNote
- protected VSChannelArray mChannelArray = null;
- protected boolean mChannelDataAvailable = false;
- protected boolean mProgramDataAvailable = false;
- // PendingChannels holds a list of channels not yet processed by GN
- // Processed channels are removed automatically
- protected ArrayList<VSChannelFromSatellite> mPendingChannels = null;
- // Hold the list of channels returned by GraceNote
- protected CopyOnWriteArrayList<VSChannel> mParsedChannels = null;
- // Create a container to hold programs by row URI and event information
- protected HashMap<Uri, EventInfoPair> mProgramMap = null;
- protected class EventInfoPair {
- protected EventInformation eventinfo;
- protected long channelID;
- }
- public static GraceNoteWrapper getInstance(){
- return SingletonHolder.mInstance;
- }
- private GraceNoteWrapper()
- {
- mChannelArray = new VSChannelArray();
- mChannelArray = new VSChannelArray();
- mPendingChannels = new ArrayList<>();
- mParsedChannels = new CopyOnWriteArrayList<>();
- mProgramMap = new HashMap<>();
- mChannelDataAvailable = false;
- mProgramDataAvailable = false;
- Log.e("GraceNote","GrancenoteWrapper created");
- }
- public boolean isParsedChannelDataAvailable() {
- return mChannelDataAvailable;
- }
- public void isParsedChannelDataAvailable(boolean state) {
- mChannelDataAvailable = state;
- }
- public boolean isParsedProgramDataAvailable() {
- return mProgramDataAvailable;
- }
- public void isParsedProgramDataAvailable(boolean state) {
- mProgramDataAvailable = state;
- }
- // Add a new channel to the pending list so that it may get parsed via GraceNote later on
- public int registerChannel(VSChannelFromSatellite channel) {
- // Get the dvbID hash value generated from the channel's onID, tsID and sID values
- int dvbIDHash = channel.getDvbID().getHash();
- // Prevent adding the same channel twice, unless the previous list was fully parsed
- // In that case, ChannelArray should skip duplicate entries automatically
- if (getChannelForDvbIDHash(dvbIDHash) == null &&
- getGraceNoteChannel(dvbIDHash) == null) {
- mPendingChannels.add(channel);
- }
- // Return the hash value so the user has a handle to work with when he wishes to retrieve
- // a specific channel's data if, for example, the channel was crated using
- // "registerChannel(ctx, new VSChannel....)"
- return dvbIDHash;
- }
- // Internally retrieve an unparsed channel based on the dvbID
- protected VSChannelFromSatellite getChannelForDvbIDHash(int dvbIDHash) {
- // Linear search is fine for a generic channel list
- for (VSChannelFromSatellite channel : mPendingChannels) {
- if (channel.getDvbID().getHash() == dvbIDHash) {
- return channel;
- }
- }
- return null;
- }
- // Retrieve a channel using its dvbID
- public VSChannel getGraceNoteChannel(int dvbIDHash) {
- // Again, linear search should be fine for a generic channel list
- for (VSChannel channel : mParsedChannels) {
- if (channel.getDvbID().getHash() == dvbIDHash) {
- return channel;
- }
- }
- return null;
- }
- public VSChannel getChannelForID(long channel_id) {
- if (mParsedChannels.isEmpty()) {
- Log.e("GraceNote", "Could not search for channel [ " + channel_id + " ]. Channel list is empty!");
- return null;
- }
- // speed up loop-based channel requests
- if (previousChannel != null &&
- previousChannel.getChannelID() == channel_id) {
- return previousChannel;
- }
- for (VSChannel channel : mParsedChannels) {
- if (channel.getChannelID() == channel_id) {
- previousChannel = channel;
- return channel;
- }
- }
- return null;
- }
- protected VSProgram getProgramByTitle(VSChannel channel, String title) {
- if (channel != null && !title.isEmpty()) {
- // Get the list of all airings for the current channel
- CopyOnWriteArrayList<VSAiring> airingList = channel.getAiringList();
- for (VSAiring airing : airingList) {
- VSProgram prog = airing.getProgram();
- if (prog != null && prog.getTitle().equalsIgnoreCase(title)) {
- return prog;
- }
- }
- }
- return null;
- }
- protected VSProgram getProgramByTitle(Long channel_id, String title) {
- if (!title.isEmpty()) {
- VSChannel channelForID = getChannelForID(channel_id);
- if (channelForID != null) {
- return getProgramByTitle(channelForID, title);
- } else {
- Log.d("GraceNote", "Could not find channel for id [ " + channel_id + " ]. Parsing all channels.");
- for (VSChannel channel : mParsedChannels) {
- VSProgram prog = getProgramByTitle(channel, title);
- if (prog != null) {
- return prog;
- }
- }
- }
- }
- return null;
- }
- public void parseChannels(String inputID, Context context) {
- new ParseGraceNoteChannels(inputID, context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- public void parsePrograms(Context context, Long startTimeMS, Long endTimeMS) {
- if (mLastStartTime != startTimeMS || mLastEndTime != endTimeMS) {
- mLastStartTime = startTimeMS;
- mLastEndTime = endTimeMS;
- isParsedProgramDataAvailable(false);
- }
- if (!isParsedProgramDataAvailable()) {
- if (!mParsedChannels.isEmpty()) {
- ParseGraceNotePrograms programParse = new ParseGraceNotePrograms(context, startTimeMS, endTimeMS, mParsedChannels);
- programParse.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- Log.e("GraceNote", "Could not parse programs. Channel list is empty!");
- }
- }
- }
- public void updateProgramInfo(Uri programURI, EventInformation eventinfo) {
- EventInfoPair infoPair = mProgramMap.get(programURI);
- if (infoPair != null) {
- infoPair.eventinfo = eventinfo;
- } else {
- Log.e("GraceNote", "Invalid update call for URI [ " + programURI.toString() + " ]" );
- }
- isParsedProgramDataAvailable(false);
- }
- public void addProgramInfo(Uri programURI, EventInformation eventinfo, long channelId) {
- EventInfoPair pair = new EventInfoPair();
- pair.eventinfo = eventinfo;
- pair.channelID = channelId;
- mProgramMap.put(programURI, pair);
- isParsedProgramDataAvailable(false);
- }
- protected String getChannelUID(String channelName, int sID, int tsID) {
- return channelName + sID + tsID;
- }
- protected class ParseGraceNotePrograms extends AsyncTask<Void, Void, Void> {
- Context context = null;
- Long mStartTime = 0L;
- Long mEndTime = 0L;
- CopyOnWriteArrayList<VSChannel> mChannels;
- public ParseGraceNotePrograms(Context context, Long startTimeMS, Long endTimeMS, CopyOnWriteArrayList<VSChannel> channels) {
- this.context = context;
- this.mStartTime = startTimeMS;
- this.mEndTime = endTimeMS;
- this.mChannels = channels;
- }
- @Override
- protected Void doInBackground(Void... params) {
- if (context != null) {
- mChannelArray.parse(context, new Date(mStartTime), new Date(mEndTime));
- CopyOnWriteArrayList<VSAiring> airingList;
- CopyOnWriteArrayList<VSContributer> contributors;
- for (VSChannel channel : mChannels) {
- airingList = channel.getAiringList();
- for (VSAiring airing : airingList) {
- VSProgram prog = airing.getProgram();
- if (prog != null) {
- if (prog.parse(context) == VSGNBase.StatusCode.OK) {
- contributors = prog.getContributers();
- for (VSContributer contributor : contributors) {
- contributor.parse(context);
- }
- VSSeries series = prog.getSeries();
- if (series != null) {
- series.parse(context);
- }
- /* Future season support
- VSSeason season = prog.getSeason();
- if (season != null) {
- season.parse(context);
- }*/
- }
- }
- }
- }
- if (!mProgramMap.isEmpty()) {
- Iterator it = mProgramMap.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<Uri, EventInfoPair> pair = (Map.Entry) it.next();
- EventInformation eventinfo = pair.getValue().eventinfo;
- long channelID = pair.getValue().channelID;
- VSProgram prog = getProgramByTitle(channelID, eventinfo.title);
- if (prog != null) {
- ContentValues content_values = new ContentValues();
- content_values.put(TvContract.Programs.COLUMN_POSTER_ART_URI, prog.getImgURL());
- context.getContentResolver().update(pair.getKey(), content_values, null, null);
- } else {
- Log.e("GraceNote", "program [ " + eventinfo.programid + " ] is null!");
- }
- }
- } else {
- Log.e("GraceNote", "no program data available for parsing!");
- }
- }
- return null;
- }
- @Override
- protected void onPreExecute() {
- Log.d("GraceNote", "GraceNote program parsing started");
- isParsedProgramDataAvailable(false);
- }
- @Override
- protected void onPostExecute(Void nothing){
- this.context = null;
- isParsedProgramDataAvailable(true);
- Log.d("GraceNote", "GraceNote program parsing finished");
- }
- }
- protected class ParseGraceNoteChannels extends AsyncTask<Void, Void, CopyOnWriteArrayList<VSChannel>> {
- Context context = null;
- Integer dvbID = null;
- String inputID = "";
- ParseGraceNoteChannels(String inputID, Context context) {
- this.context = context;
- this.inputID = inputID;
- if (mCache == null) {
- mCache = new ImageCache(context, RAM_CACHE_SIZE);
- }
- }
- ParseGraceNoteChannels(String inputID, Context context, Integer dvbID) {
- this.context = context;
- this.dvbID = dvbID;
- this.inputID = inputID;
- if (mCache == null) {
- mCache = new ImageCache(context, RAM_CACHE_SIZE);
- }
- }
- @Override
- protected CopyOnWriteArrayList<VSChannel> doInBackground(Void... params) {
- CopyOnWriteArrayList<VSChannel> channelsOut = new CopyOnWriteArrayList<>();
- VSGNBase.StatusCode gnParseStatus = VSGNBase.StatusCode.OTHER;
- if (dvbID == null) {
- gnParseStatus = mChannelArray.parseGNIDsWithChannels(context, mPendingChannels, false);
- } else {
- VSChannelFromSatellite channel = getChannelForDvbIDHash(dvbID);
- if (channel != null) {
- gnParseStatus = mChannelArray.parseGNIDWithChannel(context, channel, false);
- }
- }
- if (gnParseStatus == VSGNBase.StatusCode.OK) {
- channelsOut = updateParsedChannels(inputID, context);
- }
- return channelsOut;
- }
- // Called after we submitted our pending channels to GraceNote for parsing
- protected CopyOnWriteArrayList<VSChannel> updateParsedChannels(String inputID, Context context) {
- // Retrieve the list of successfully parsed channels
- CopyOnWriteArrayList<VSChannel> channelsOut = mChannelArray.getChannelList();
- // Create a container to map a channel URI to a channel logo URL
- HashMap<Uri, String> logos = new HashMap<>();
- // Get all channels by querying TvInputManager
- ContentResolver cr = context.getContentResolver();
- // We need as much data as possible to match Android channels with GraceNote channels
- String[] projection = {
- TvContract.Channels._ID,
- TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID,
- TvContract.Channels.COLUMN_SERVICE_ID,
- TvContract.Channels.COLUMN_DISPLAY_NAME,
- };
- // Attempt to match them with the live channel list used by AndroidTV
- // Create a container to hold our existing android channels
- HashMap<String, Long> existingChannelsMap = new HashMap<>();
- // Create a container to hold the URI for each android channel
- HashMap<Long, Uri> channelURIMap = new HashMap<>();
- Uri uri = TvContract.buildChannelsUriForInput(inputID);
- // Try and build a list of channels with our requested data
- Cursor cursor = cr.query(uri, projection, null, null, null);
- // Move the cursor over every channel
- while (cursor != null && cursor.moveToNext()) {
- // Generate a unique key to match channels later on
- long rowID = cursor.getLong(0);
- int tsID = cursor.getInt(1);
- int sID = cursor.getInt(2);
- String name = cursor.getString(3);
- // Store channel data in our mapping containers
- Uri channelUri = ContentUris.withAppendedId(TvContract.Channels.CONTENT_URI, rowID);
- existingChannelsMap.put(getChannelUID(name, sID, tsID), rowID);
- channelURIMap.put(rowID, channelUri);
- }
- if (cursor != null) {
- cursor.close();
- }
- Uri channelUri;
- // We iterate over every GraceNote parsed channel
- for (VSChannel newChannel : channelsOut) {
- // Try to generate a unique key for the current channel the same way we did above
- int tsID = newChannel.getDvbID().getTsID();
- int sID = newChannel.getDvbID().getsID();
- String name = newChannel.getName();
- // Attempt to find a valid match within the list of android channels
- Long rowId = existingChannelsMap.get(getChannelUID(name, sID, tsID));
- if (rowId != null) {
- newChannel.setChannelID(rowId);
- // If we found a match, retrieve the channelURI and save it to our logo map
- channelUri = channelURIMap.get(rowId);
- // And check that it has a valid logo
- String channelLogo = newChannel.getImgURL();
- if (channelLogo != null && !channelLogo.isEmpty()) {
- logos.put(channelUri, newChannel.getImgURL());
- }
- }
- }
- // Download all of the needed logos upfront (to retrieve them later on)
- // This is done asynchronously as well
- mCache.cacheLogos(logos);
- return channelsOut;
- }
- @Override
- protected void onPreExecute() {
- Log.d("GraceNote", "GraceNote channel parsing started");
- isParsedChannelDataAvailable(false);
- }
- @Override
- protected void onPostExecute(CopyOnWriteArrayList<VSChannel> parsedChannels){
- mParsedChannels = parsedChannels;
- mPendingChannels.clear();
- isParsedChannelDataAvailable(true);
- Log.d("GraceNote", "GraceNote channel parsing finished. Parsed [ " + mParsedChannels.size() + " ] channels");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement