TiVo Community
TiVo Community
TiVo Community
Go Back   TiVo Community > Underground Playground > Developers Corner
TiVo Community
Reply
Forum Jump
 
Thread Tools
Old 09-01-2013, 03:49 PM   #61
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Angry

Quote:
Originally Posted by moyekj View Post
The TiVo Roamio series that just launched has built in Opera web browser with HTML5 support. After some fussing around I discovered a way to display any arbitrary web page on my Roamio Plus.
DAMMIT!!
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 09-04-2013, 01:51 PM   #62
Fofer
༺♥༻
 
Fofer's Avatar
 
Join Date: Oct 2000
Location: Neither here nor there
Posts: 69,895
TC CLUB MEMBER
Quote:
Originally Posted by davidblackledge View Post
DAMMIT!!
Your work here was amazing. In fact, there are probably users with older TiVos who would still be happy to see it, and use it, since that new built-in browser feature is a Roamio exclusive. Who knows, maybe that new feature will bring renewed attention to Enter Webz?!?!

I personally have little interest in a Roamio at this time... but would love to enhance my current Premiere with cool add-ons such as yours.

And I'm sure you learned a great deal developing Enter Webz. Kudos to you, and thanks. Keep your chin up! You're brilliant!
__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
- a list of some favorite browser add-ons that help make TCF even more enjoyable!
Fofer is offline   Reply With Quote
Old 11-01-2013, 12:54 AM   #63
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Arrow October Enter Webz Beta update

​​​October Enter Webz Beta update - the Halloween Update! (ok, there's nothing scary about this...unless you mean scary AWESOME!)

Sorry about the 7 month lag. I was occupied with my wife's open-heart surgery & continuing recovery, and I have been playing a lot of Team Fortress 2 ;] (Pyro FTW!)

Download it from david.blackledge.com/tivo/enterwebz​

Major enhancements (More detailed list is in the documentation):

  • Videos and Audio play in-browser, PIP works so you can keep browsing, much better support in web pages.
  • RSS & Atom Feed support - often a better option than the actual page
  • More Images load now - Facebook pictures and Gocomics.com work! Even Icanhascheezburger.com works! (RSS feed is better)
  • ​thumztak Organizing - groups, order, editing
  • Cookie improvements - lots of pages work better​, and "delete all cookies" to fix problems
  • Fixed Mac and Linux issues (hopefully)
Also: More fonts (serif, fixed, and script!), better navigation (mobile num shortcuts, "B"ack, Clear only quits), new UI graphics (still needs work), useful idle handling, fixed Live TV & many bugs, added new bugs ;]

​I want to emphasize the new RSS support. It is the better way to browse most content, providing a much simpler web page. Archive.org has one for each category's recent uploads, futoncritic's covers half the site, and tivocommunity.com and most blogs and news sites have one. Note that RSS via feedburner (such as ICanHasCheezburger) now ignores their crazy stylesheet.

My Next Goals: custom in-page focus manager and highlights, youtube playlists and on-the-fly audio/video playlists, complete main theme and theme system, edit thumztak url and icon, bigger list of useful compatible links, bug fixes... and a Public Server! (and some ads to pay for it)

Some known website issues:
  • Google services work fine... but later password verification can get stuck and you have to delete all cookies. The Google search page refuses to show the mobile version.
  • Yahoo services refuse to login with Enter Webz' Mobile mode, and logins aren't quite right in non-Mobile mode.​
  • Facebook videos don't show up - complain to Facebook. The same thing happens on my PalmOS phone's browser - they just don't send any HTML for the video at all!
  • While table layout was improved, the last column is still often broken, even a little worse now.
  • Vimeo: home page will reboot your TiVo. I did a lot of work to support their videos, but they recently changed so now I can't support it at all.

Realistically, Enter Webz is better thought of as an App Platform for the TiVo. I've gathered some examples that use no scripting or plugins and are simple games, slideshows, and jukeboxes that work nicely. Targeting Enter Webz with a website design is much easier than writing an HME App.

Please post your favorite websites/feeds/apps to view in Enter Webz so I can add them to my list! I like http://m.podcast.tv and http://shoutcast.com not to mention http://m.facebook.com http://xkcd.com and http://gocomics.com

And post your favorite sites and RSS feeds that don't quite work so I can try to tackle bugs that might be in your way.
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 11-01-2013, 07:33 AM   #64
dadrepus
Registered User
 
dadrepus's Avatar
 
Join Date: Jan 2012
Posts: 65
Wink Tried it with a Mac running 10.9

Just opened the Command file in terminal but other than this:
Last login: Wed Oct 30 22:10:05 on console
Alexs-Mac-mini:~ Alex$ /Applications/EnterWebzDist-2013-10-31/Enter\ Webz.command ; exit;
logout

[Process completed]
Nothing else happened. So I tried to directly open the jar file. (Now with Mavericks 10.9 one cannot easily open files by an unrecognized developer. One must hold down control button while clicking on an application or file) Well, the jar fails to open. Says go to console app to find error. Look at console but cannot find error so far. don't know exactly what the error would be called. I will continue to examine console for error. Glad your wife is doing better
dadrepus is offline   Reply With Quote
Old 11-01-2013, 08:53 AM   #65
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by dadrepus View Post
Just opened the Command file in terminal but other than this:
Last login: Wed Oct 30 22:10:05 on console
Alexs-Mac-mini:~ Alex$ /Applications/EnterWebzDist-2013-10-31/Enter\ Webz.command ; exit;
logout

[Process completed]
Nothing else happened. So I tried to directly open the jar file. (Now with Mavericks 10.9 one cannot easily open files by an unrecognized developer. One must hold down control button while clicking on an application or file) Well, the jar fails to open. Says go to console app to find error. Look at console but cannot find error so far. don't know exactly what the error would be called. I will continue to examine console for error. Glad your wife is doing better
Ok, somebody send me a Mac and I'll test it ;]
Strange that the behavior seems so different. All I believe I did since last release is fix newlines in the command file and mark it as executable.

Let me know if you find any output, (I'd hope relevant stuff would either mention "java" or "com.blackledge.david" etc. - the java package names) but otherwise we'll need a local Mac expert to get it working and enlighten us :/

Thanks for trying it!
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.

Last edited by davidblackledge : 11-01-2013 at 08:58 AM. Reason: include hint for finding errors in console
davidblackledge is offline   Reply With Quote
Old 11-03-2013, 01:49 PM   #66
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Note Technical items of interest

In the latest release of Enter Webz:

Video/PIP is handled with three features:
1) all video (including "livetv:") is currently handled by launching TiVo's VideoPlayer or Youtube Player app with detail parameters passed in. But it now does it via the "Application as Stream" feature. This is broken in the Java SDK, but easily worked around (see the wiki).
(in the future I should put "livetv:" in a custom handler so you don't have to wait for the VideoPlayer app to launch)
2) Scaling, like I mentioned previously, is handled with a setting the View's scale and position, but the position has to NOT be up against the upper and left edges of the screen or the scale is ignored by the video stream (and destabilizes I think)
3) Most interesting: I finally realized what the Send Event command is REALLY for (not just for animation chaining per the SDK documentation). It actually sends the event to the targeted Stream... if that stream is an Application, then it's like you hit that remote button. For my purposes, when the player is full screen, I forward every event except for two that I want to override (Zoom/Aspect/Window/PIP and Left - both of which scale/position to PIP mode). When it's in PIP mode I only forward the Pause button.


Images: I guess all https resource URLs are mishandled by the TiVo, so that caused lots of images to fail in webpages... instead I just replace them all with http URLs and hope for the best. Usually it works. (there is a bug in this release where my "figure out the size" code isn't handling the replaced URLs correctly - fixed in next release). There are still lots of sites that protect against remote loading, and I haven't gotten a solution for telling the TiVo to send referer/cookie information in its request.


Fonts: I found some freely distributable fonts that fit the bill and put them on my main website, then just tell the TiVo to download the font from there when I need it, and re-use the font resource for the rest of the session.
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 11-03-2013, 05:48 PM   #67
wmcbrine
Resistance Useless
 
wmcbrine's Avatar
 
Join Date: Aug 2003
Posts: 9,076
Quote:
Originally Posted by davidblackledge View Post
1) all video (including "livetv:") is currently handled by launching TiVo's VideoPlayer or Youtube Player app with detail parameters passed in. But it now does it via the "Application as Stream" feature. This is broken in the Java SDK, but easily worked around (see the wiki).
Interesting. Uh, where exactly in the wiki?
__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
wmcbrine is offline   Reply With Quote
Old 11-03-2013, 10:41 PM   #68
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Note V49 Java SDK fixes/classes

Quote:
Originally Posted by wmcbrine View Post
Interesting. Uh, where exactly in the wiki?
ok, the wiki's not that well organized.

SDKs > Java SDK Bugs / Gotchas
http://hmedev.wikidot.com/java-sdk-bugs-gotchas
The last entry (parseQuery)

That's specifically a bug in the Java SDK code itself.

Actually, I'll soon stick on the wiki the three classes I put together to encapsulate all I could of the V49 changes for the Java SDK and to make using the 1.4.1e version of the SDK easier.

Let's see if I can get them into this post:
V49IHmeProtocol.java - just the additional constants for the keyboard and video status, etc.
V49BApplicationFactory.java - report your app as V49 so you can use new features
V49BApplication.java - helpers for several V49 features, and fixes for some problems (some are pre 1.4.1e problems that don't need fixing if you use the newer SDK, so I made them forward compatible fixes).

Code:
V49IHmeProtocol.java
Code:
package com.blackledge.david.tivo;

import com.tivo.hme.interfaces.IHmeConstants;
import com.tivo.hme.sdk.IHmeProtocol;

/**
 * IHmeProtocol extension that supports some features beyond SDK 1.4.1
 * especially HTTP Header strings and Slide Remote key codes. Typically just use
 * {@link #KEY_OPT_ASCII_START}, {@link #KEY_OPT_ASCII_END}, and
 * {@link #KEY_OPT_ASCII_OFFSET} to get all the characters.
 * 
 */
public interface V49IHmeProtocol extends IHmeProtocol {
	/**
	 * 0.49 - Slide Remote key events supported (no "supporting" sdk version)
	 * (0.41 ({@link IHmeProtocol#VERSION_0_41}) supported by sdk 1.4, 0.43-0.45
	 * ({@link IHmeProtocol#VERSION_0_43}-{@link IHmeProtocol#VERSION_0_45}) by
	 * sdk 1.4.1e)
	 */
	public static final int VERSION_0_49 = (0 << 8) | 49;

	/**
	 * according to an error logged:
	 * "rendered text exceeded max allowed dimensions of 1920x1080"
	 */
	public static final int LIMIT_TEXT_RENDER_WIDTH = 1920;
	/**
	 * according to an error logged:
	 * "rendered text exceeded max allowed dimensions of 1920x1080"
	 */
	public static final int LIMIT_TEXT_RENDER_HEIGHT = 1080;
	
	/** Media status code, resource at end of stream. */
	public static final int RSRC_STATUS_END = 11;
	/** Media status code, resource at end of available buffer. */
	public static final int RSRC_STATUS_BUFFER_OVERFLOW = 12;
	
    /**
	 * Zoom key, optional, relabel of {@link #KEY_OPT_ASPECT} key, which is same
	 * code as {@link #KEY_OPT_WINDOW} and {@link #KEY_OPT_PIP} (22).
	 */
    public static final int KEY_OPT_ZOOM			= KEY_OPT_WINDOW;
    
    // undefined keys in SDK: 0-21, 23, 25, 28-50
    
    /**
	 * On Demand key, reserved for internal use. E.g. long blue ON DEMAND button
	 * on Charter remote. This is sent in a key press event just before
	 * attempting to "teleport" to the service. In anything below Series 4, no
	 * teleport and not transmitted over HME, apparently.
	 */
    public static final int KEY_OPT_ON_DEMAND = 30;
    
    // last SDK key code defined: KEY_OPT_DVD = 55;
    
	/**
	 * "A" yellow remote button, may only transmit on if identified as V49.
	 */
	public static final int KEY_OPT_A_YELLOW = 56;
	/**
	 * "B" blue remote button, may only transmit on if identified as V49.
	 */
	public static final int KEY_OPT_B_BLUE = 57;
	/**
	 * "C" red remote button, may only transmit on if identified as V49.
	 */
	public static final int KEY_OPT_C_RED = 58;
	/**
	 * "D" green remote button, may only transmit on if identified as V49.
	 */
	public static final int KEY_OPT_D_GREEN = 59;
	
	/**
	 * Backspace (picture of a left arrow on slide remote) button code.<BR>
	 */
	public static final int KEY_OPT_BACKSPACE = 65;
	
	// codes 60-64 and 66-69 are unknown, currently
	
	/**
	 * code returned by the RETURN key on the keyboard if it is
	 * modified by Alt (or Windows or Ctrl (or possibly "sym"(bol))). Normally
	 * that key sends KEY_SELECT.
	 */
	public static final int KEY_OPT_ALT_SELECT = 70;
	/**
	 * Left Shift button code. You do not need to process this to handle
	 * capitalization, use KEY_OPT_ASCII_* to get the properly capitalized
	 * character.
	 */
	public static final int KEY_OPT_LEFT_SHIFT = 71;
	/**
	 * Right Shift button code. You do not need to process this to handle
	 * capitalization, use KEY_OPT_ASCII_* to get the properly capitalized
	 * character.
	 */
	public static final int KEY_OPT_RIGHT_SHIFT = 72;
	/**
	 * Left Alt (and Windows) key button code for keyboards - POSSIBLY the
	 * "sym"(bol) key for the Slide Remote (although there is only one, on the
	 * right side). You do not need to process this to handle symbols, use
	 * KEY_OPT_ASCII_* to get the properly capitalized character.
	 */
	public static final int KEY_OPT_LEFT_ALT = 73;
	/**
	 * Right Alt (and Windows) key button code for keyboards - POSSIBLY the
	 * "sym"(bol) key for the Slide Remote. You do not need to process this to
	 * handle symbols, use KEY_OPT_ASCII_* to get the properly capitalized
	 * character.
	 */
	public static final int KEY_OPT_RIGHT_ALT = 74;
	/**
	 * Capslock button code. You do not need to process this to handle
	 * capitalization, use KEY_OPT_ASCII_* to get the properly capitalized
	 * character.
	 */
	public static final int KEY_OPT_CAPSLOCK = 75;
	
	/**
	 * For all characters between KEY_OPT_ASCII_START and KEY_OPT_ASCII_END
	 * (inclusive) subtract this value from the key code to get the ASCII
	 * character they represent.
	 */
	public static final int KEY_OPT_ASCII_OFFSET = 65536; // 2^16
	public static final int KEY_OPT_ASCII_SPACE = KEY_OPT_ASCII_OFFSET+' ';
	// Sym Q
	public static final int KEY_OPT_ASCII_EXCLAMATION = KEY_OPT_ASCII_OFFSET+'!';
	// Sym L
	public static final int KEY_OPT_ASCII_QUOTE = KEY_OPT_ASCII_OFFSET+'\"';
	// Sym E
	public static final int KEY_OPT_ASCII_HASH = KEY_OPT_ASCII_OFFSET+'#';
	// Sym R
	public static final int KEY_OPT_ASCII_DOLLAR = KEY_OPT_ASCII_OFFSET+'$';
	// Sym T
	public static final int KEY_OPT_ASCII_PERCENT = KEY_OPT_ASCII_OFFSET+'%';
	// Sym U
	public static final int KEY_OPT_ASCII_AMPERSAND = KEY_OPT_ASCII_OFFSET+'&';
	// Sym K
	public static final int KEY_OPT_ASCII_APOSTROPHE = KEY_OPT_ASCII_OFFSET+'\'';
	// Sym O
	public static final int KEY_OPT_ASCII_LEFTPAREN = KEY_OPT_ASCII_OFFSET+'(';
	// Sym P
	public static final int KEY_OPT_ASCII_RIGHTPAREN = KEY_OPT_ASCII_OFFSET+')';
	// Sym I
	public static final int KEY_OPT_ASCII_ASTERISK = KEY_OPT_ASCII_OFFSET+'*';
	// Sym 1
	public static final int KEY_OPT_ASCII_PLUS = KEY_OPT_ASCII_OFFSET+'+';
	// Sym B
	public static final int KEY_OPT_ASCII_COMMA = KEY_OPT_ASCII_OFFSET+',';
	// Sym 2
	public static final int KEY_OPT_ASCII_MINUS = KEY_OPT_ASCII_OFFSET+'-';
	// Sym N
	public static final int KEY_OPT_ASCII_PERIOD = KEY_OPT_ASCII_OFFSET+'.';
	// Sym 5
	public static final int KEY_OPT_ASCII_SLASH = KEY_OPT_ASCII_OFFSET+'/';
	// 0-9 use KEY_NUM0-KEY_NUM9
	// Sym J
	public static final int KEY_OPT_ASCII_COLON = KEY_OPT_ASCII_OFFSET+':';
	// Sym H
	public static final int KEY_OPT_ASCII_SEMICOLON = KEY_OPT_ASCII_OFFSET+';';
	// Sym Z
	public static final int KEY_OPT_ASCII_LESS = KEY_OPT_ASCII_OFFSET+'<';
	// Sym 3
	public static final int KEY_OPT_ASCII_EQUAL = KEY_OPT_ASCII_OFFSET+'=';
	// Sym X
	public static final int KEY_OPT_ASCII_GREATER = KEY_OPT_ASCII_OFFSET+'>';
	// Sym M
	public static final int KEY_OPT_ASCII_QUESTION = KEY_OPT_ASCII_OFFSET+'?';
	// Sym W
	public static final int KEY_OPT_ASCII_AT = KEY_OPT_ASCII_OFFSET+'@';
	public static final int KEY_OPT_ASCII_A_UPPER = KEY_OPT_ASCII_OFFSET+'A';
	public static final int KEY_OPT_ASCII_Z_UPPER = KEY_OPT_ASCII_OFFSET+'Z';
	// Sym F
	public static final int KEY_OPT_ASCII_LEFTBRACKET = KEY_OPT_ASCII_OFFSET+'[';
	// Sym V
	public static final int KEY_OPT_ASCII_BACKSLASH = KEY_OPT_ASCII_OFFSET+'\\';
	// Sym G
	public static final int KEY_OPT_ASCII_RIGHTBRACKET = KEY_OPT_ASCII_OFFSET+']';
	// Sym Y
	public static final int KEY_OPT_ASCII_CIRCUMFLEX = KEY_OPT_ASCII_OFFSET+'^';
	// Sym 7
	public static final int KEY_OPT_ASCII_UNDERSCORE = KEY_OPT_ASCII_OFFSET+'_';
	// Sym 9
	public static final int KEY_OPT_ASCII_GRAVE = KEY_OPT_ASCII_OFFSET+'`';
	public static final int KEY_OPT_ASCII_A_LOWER = KEY_OPT_ASCII_OFFSET+'a';
	public static final int KEY_OPT_ASCII_Z_LOWER = KEY_OPT_ASCII_OFFSET+'z';
	// Sym S
	public static final int KEY_OPT_ASCII_LEFTBRACE = KEY_OPT_ASCII_OFFSET+'{';
	// Sym C
	public static final int KEY_OPT_ASCII_BAR = KEY_OPT_ASCII_OFFSET+'|';
	// Sym D
	public static final int KEY_OPT_ASCII_RIGHTBRACE = KEY_OPT_ASCII_OFFSET+'}';
	// Sym A
	public static final int KEY_OPT_ASCII_TILDE = KEY_OPT_ASCII_OFFSET+'~';
	/**
	 * space character - beginning of range of values that are ASCII characters
	 * plus KEY_OPT_ASCII_OFFSET. Note that 0-9 do not show up this way,
	 * instead sending the KEY_NUM* codes.
	 */
	public static final int KEY_OPT_ASCII_START = KEY_OPT_ASCII_SPACE;
	/**
	 * tilde character - end of range of values that are ASCII characters plus
	 * KEY_OPT_ASCII_OFFSET. Note that 0-9 do not show up this way,
	 * instead sending the KEY_NUM* codes.
	 */
	public static final int KEY_OPT_ASCII_END = KEY_OPT_ASCII_TILDE;

	// as discovered by davidblackledge - Premiere only.
	public static final int ID_FONT3_TTF = 13;
	public static final int ID_FONT3ITALIC_TTF = 14;
	public static final int ID_FONT3BOLD_TTF = 15;
	// as discovered by wmcbrine - Premiere only
	public static final int ID_SPEEDUP4_SOUND = 37;
	
	/**
	 * HTTP Header sent in resource requests by the TiVo with the tsn (context
	 * connection attribute "tsn") as value.
	 */
	public static final String HTTP_HEADER_TIVO_ID = "TiVo_TCD_ID";

	/**
	 * HTTP Header sent in resource requests by the TiVo with the TiVo Software
	 * Version (Device Info event's "version") as value.
	 */
	public static final String HTTP_HEADER_TIVO_VERSION = "TiVo_SW_VER";

	public static final String HTTP_HEADER_TIVO_DURATION = IHmeConstants.TIVO_DURATION;

}
V49BApplication.java
Code:
package com.blackledge.david.tivo;

import java.awt.Rectangle;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.net.URLDecoder;
import java.util.Map;
import java.util.LinkedHashMap;

import com.tivo.hme.bananas.BApplication;
import com.tivo.hme.interfaces.IContext;
import com.tivo.hme.sdk.Application;
import com.tivo.hme.sdk.HmeEvent;
import com.tivo.hme.sdk.HmeEvent.DeviceInfo;
import com.tivo.hme.sdk.IHmeProtocol;
import com.tivo.hme.sdk.Resource;
import com.tivo.hme.sdk.Version;

/**
 * BApplication that fixes SDK bugs, supports some features beyond SDK 1.4.1 and
 * makes some things easier. See {@link V49BApplicationFactory} and
 * {@link V49IHmeProtocol} for other features.
 * <UL>
 * <LI>Use {@link V49BApplicationFactory} as superclass for your factory to tell the TiVo you're using V49 (or another version).
 * <LI>Constants for SDK resource strings *.ttf, *.snd
 * <LI>Constants for discovered Stream resources "livetv:" "loopset:" and
 * "recording:"
 * <LI>Getters for spacing when a "loopset:" is the background
 * <LI>Member variables for protocol version, tivo version, and tivo ID.
 * <LI>Resolution help: automatically set preferred resolution, template methods
 * for init and showing the first BScreen during resolution setting
 * <LI>Template method for cleaning up during {@link #destroy()} to prevent an
 * SDK 1.4 bug (not an issue in 1.4.1e)
 * <LI>Post Resource errors to the resource and with new version of
 * {@link #handleApplicationError(int, String, Integer)}
 * <LI>Fix SDK bug that broke Application-as-stream feature.
 * <LI>Support more TTF built-in fonts with new constant names for series-4-only
 * fonts, and with id numbers-as-font-names for arbitrary attempts.
 * <LI>SDK capability/version methods.
 * <LI>Backward compatibility of new SDK methods to old SDK. You should be able
 * to run this app in either SDK.
 * </UL>
 * 
 * @author David.Blackledge.com
 * 
 */
public abstract class V49BApplication extends BApplication implements V49IHmeProtocol {

    public static final String TTF_SERIES4FONT3BOLD = "series4font3bold.ttf";
	public static final String TTF_SERIES4FONTITALIC = "series4fontitalic.ttf";
	public static final String TTF_SERIES4FONT = "series4font.ttf";
	public static final String TTF_DEFAULT = "default.ttf"; //$NON-NLS-1$
    public static final String TTF_SYSTEM = "system.ttf"; //$NON-NLS-1$
    
    public static final String SOUND_BONK = "bonk.snd"; //$NON-NLS-1$
    public static final String SOUND_UPDOWN = "updown.snd"; //$NON-NLS-1$
    public static final String SOUND_THUMBSUP = "thumbsup.snd"; //$NON-NLS-1$
    public static final String SOUND_THUMBSDOWN = "thumbsdown.snd"; //$NON-NLS-1$
    public static final String SOUND_SELECT = "select.snd"; //$NON-NLS-1$
    public static final String SOUND_TIVO = "tivo.snd"; //$NON-NLS-1$
    public static final String SOUND_LEFT = "left.snd"; //$NON-NLS-1$
    public static final String SOUND_RIGHT = "right.snd"; //$NON-NLS-1$
    public static final String SOUND_PAGEUP = "pageup.snd"; //$NON-NLS-1$
    public static final String SOUND_PAGEDOWN = "pagedown.snd"; //$NON-NLS-1$
    public static final String SOUND_ALERT = "alert.snd"; //$NON-NLS-1$
    public static final String SOUND_DESELECT = "deselect.snd"; //$NON-NLS-1$
    public static final String SOUND_ERROR = "error.snd"; //$NON-NLS-1$
    public static final String SOUND_SLOWDOWN1 = "slowdown1.snd"; //$NON-NLS-1$
    public static final String SOUND_SPEEDUP1 = "speedup1.snd"; //$NON-NLS-1$
    public static final String SOUND_SPEEDUP2 = "speedup2.snd"; //$NON-NLS-1$
    public static final String SOUND_SPEEDUP3 = "speedup3.snd"; //$NON-NLS-1$
    
	public static final String STREAM_LIVETV = "livetv:"; //$NON-NLS-1$
	public static final String STREAM_LOOP_RED_CENTRAL = "loopset:Central"; //$NON-NLS-1$
	public static final String STREAM_LOOP_PURPLE_SHOWCASES = "loopset:Showcases"; //$NON-NLS-1$
	public static final String STREAM_LOOP_BLUE_SETUP = "loopset:Setup"; //$NON-NLS-1$
	public static final String STREAM_LOOP_GREEN_NOWPLAYING = "loopset:NowPlaying"; //$NON-NLS-1$
	public static final String STREAM_RECORDING_PREFIX = "recording:"; //$NON-NLS-1$
	
    
	/**
	 * Protocol in use between the TiVo and the server. Used in methods like
	 * {@link #isSlideRemoteSupported()}. Accurate/dynamic version of
	 * {@link IHmeProtocol#VERSION}. Saved during
	 * {@link #setContext(IContext, int)} call. Use V49BapplicationFactory as
	 * your factory's supertype to register V49 as your preferred protocol
	 * version.
	 */
	public int protocolVersion;
	/**
	 * Device Info event's "version" - the TiVo's Software Version. E.g.
	 * 11.0k-01-2-652 . Available after DEVICE_INFO_EVENT comes in.
	 */
	protected String tivoVersion;
	/**
	 * The TiVo Service Number (tsn) uniquely identifying the connected TiVo DVR
	 * device. Available after {@link #setContext(IContext, int)} is called.
	 */
	protected String tivoID;

	/**
	 * Does nothing.  Override this to output debug messages
	 * @param message
	 */
	public void debug(String message) {
	}

	/**
	 * Template method to do {@link #init(IContext)} tasks between super's init
	 * and preferred resolution setting. Better to override this than init
	 * unless you want to handle setting resolution yourself.
	 */
	protected void initBeforeResolutionSet(IContext context) {
	}

	/**
	 * Template method to do {@link #rootBoundsChanged(Rectangle)} tasks between
	 * super's rootBoundsChanged and a possible call to {@link #showFirstPage()}
	 * if this is the first root bounds change during application
	 * initialization. Override this, or it might be OK to override
	 * rootBoundsChanged and just call its super method and ignore this.
	 * 
	 * @param rootBounds
	 */
	protected void rootBoundsChangedBeforeFirstPage(Rectangle rootBounds) {
	}

	/**
	 * Override this to push the first BScreen of the application after
	 * resolution issues are resolved.
	 */
	protected abstract void showFirstPage();

	/**
	 * Override this instead of {@link #destroy()} for SDK 1.4 to do safe cleanup during the
	 * destroy operation. Prevents the loop that occurs if a fatal error happens
	 * during destroy.  Not an issue in 1.4.1e
	 */
	protected void destroyCleanup() {
	}
	
	
	/* BEGIN fix JDK */
	

	// TODO future: handle unsupported chunks (e.g. Event 10)
	// public boolean handleChunk(InputStream in)
	// {
	// synchronized (lock) {
	// //debug("handleChunk()");
	// boolean doMore = true;
	//
	// // flush any data that was generated from previous handling of
	// // event
	// flush();
	//
	// ChunkedInputStream chunkInStr = null;
	// if (in instanceof ChunkedInputStream)
	// {
	// chunkInStr = (ChunkedInputStream)in;
	// }
	// else
	// {
	// chunkInStr = new ChunkedInputStream(in); //,
	// IHmeConstants.TCP_BUFFER_SIZE);
	// }
	//
	// // if ( protocolVersion < VERSION_0_40 )
	// // {
	// // chunkInStr.setUseVString( false );
	// // }
	// // else {
	// chunkInStr.setUseVString( true );
	// // }
	//
	// int opcode = -1;
	// try {
	// opcode = (int)chunkInStr.readVInt();
	// } catch (IOException e) {
	// // receiver closed - ignore
	// // if (debug()) {
	// // log(ILogger.LOG_DEBUG,
	// // "Connection terminated by receiver");
	// // }
	// }
	// if (opcode == -1) {
	// doMore = false;
	// return doMore;
	// }
	//
	// HmeEvent evt = null;
	// String eventString = null;
	// try
	// {
	// switch (opcode) {
	// case EVT_DEVICE_INFO:
	// evt = new HmeEvent.DeviceInfo(chunkInStr);
	// break;
	// case EVT_APP_INFO:
	// evt = new HmeEvent.ApplicationInfo(chunkInStr);
	// break;
	// case EVT_RSRC_INFO:
	// evt = new HmeEvent.ResourceInfo(chunkInStr, this);
	// break;
	// case EVT_RESOLUTION_INFO:
	// evt = new HmeEvent.ResolutionInfo(chunkInStr);
	// break;
	// case EVT_KEY:
	// evt = new HmeEvent.Key(chunkInStr);
	// break;
	// case EVT_IDLE:
	// evt = new HmeEvent.Idle(chunkInStr);
	// break;
	// case EVT_FONT_INFO:
	// evt = new HmeEvent.FontInfo(chunkInStr);
	// break;
	// case EVT_INIT_INFO:
	// evt = new HmeEvent.InitInfo(chunkInStr);
	// break;
	// default:
	// eventString =
	// "HmeEvent[opcode=" + opcode
	// + ", id = " + chunkInStr.readVInt()
	// + "]";
	// // short clen = chunkInStr.readShort();
	// // while (clen != 0) {
	// // System.out.println(clen);
	// // chunkInStr.skip(clen);
	// // clen = chunkInStr.readShort();
	// // }
	//
	// // System.out.println(eventString);
	// // try {
	// // System.out.println(chunkInStr.readInt());
	// // System.out.println(chunkInStr.readDict());
	// // } catch(IOException e1) {
	// // chunkInStr.readTerminator();
	// // throw e1;
	// // }
	// break;
	// }
	// if (evt != null) {
	// evt.setMonitor(lock);
	// }
	// chunkInStr.readTerminator();
	// }
	// catch (IOException e) {
	// evt = null;
	// getLogger().log(ILogger.LOG_INFO, e);
	// }
	//
	// //
	// // Save the event, in case we need to dump the list
	// //
	// // if (eventsReceived != null) {
	// // if (eventsReceived.size() >= MAX_RECEIVED_EVENTS_SIZE) {
	// // // Startup is complete -- stop checking for protocol errs
	// // startupComplete = true;
	// // eventsReceived.clear();
	// // eventsReceived = null;
	// // } else {
	// // if (evt != null) {
	// // eventString = evt.toString();
	// // }
	// // if (eventString == null) {
	// // eventString = "Bad HmeEvent[opcode="+opcode+", no ID]";
	// // }
	// // eventsReceived.add(eventString);
	// // }
	// // }
	//
	// if (evt == null) {
	// getLogger().log(ILogger.LOG_DEBUG,
	// "unknown event opcode : " + opcode);
	// }
	// else
	// {
	// // if any debugging is turned on, verify the event is kosher
	// // if (debug()) {
	// // evt.verify(logger);
	// // }
	//
	// // debugEvents means to print each and every event received
	// // if (debugEvents()) {
	// getLogger().log(ILogger.LOG_DEBUG, "event " + evt);
	// // }
	//
	// // if (!preprocessEvent(evt)) {
	// //
	// // // preprocessEvent() says this event should be discarded
	// // if (eventsReceived != null) {
	// // int i = eventsReceived.size() - 1;
	// // eventsReceived.set(i,
	// // eventsReceived.get(i).toString() + " [IGNORED]");
	// // }
	//
	// // } else {
	//
	// // The app should receive this event.
	// //
	// // Only dispatch events after app.init() is called.
	// // Save events before init(), to be dispatched later.
	// //
	// // if (appInitialized) {
	// // dispatchEvent(evt);
	// // } else if (queuedEvents != null) {
	// // // Save the events to send after initialization
	// // queuedEvents.add(evt);
	// // }
	// // }
	// }
	//
	// // flush any data that was generated from handling of event
	// flush();
	//
	// return doMore;
	// } // sync
	//
	// } // handleChunk()


	/**
	 * unfortunately sdk's Resource.ResourceStatus isn't public, so we recreate
	 * it here - all it does is use a different Event ID
	 */
	protected static class MockResourceStatus extends HmeEvent.ResourceInfo {
		MockResourceStatus(int id, Resource rsrc, int status, Map map) {
			super(EVT_RSRC_STATUS, id, rsrc, status, map);
		}

		public String toString() {
			return getID() + ".RSRC_STATUS(" + statusToString(getStatus()) //$NON-NLS-1$
					+ ")"; //$NON-NLS-1$
		}
	}

	private boolean destroyedAlready = false;

	public void destroy() {
		// protect against SDK 1.4 bug: if there is a fatal error during below
		// operations (e.g. remove operations) close gets called which calls
		// destroy again.
	
		// what happens: after the 2nd call to here, we'll get HMEException from
		// the remove call that caused it which contains the actual cause
		// (unless it was originally an HMEException)
		// setId(-1) has not been called on the object yet
	
		// SO: want to catch HMEExceptions if we want to finish our destroy
		// operation
		if (destroyedAlready)
			return;
		destroyedAlready = true;
	
		// template method
		destroyCleanup();
		// ... operations that could cause a fatal error, e.g. "remove" calls
	
		super.destroy(); // in case e.g. BApplication ever starts doing
							// something there.
	}
	
	/**
	 * Improved version of
	 * {@link Application#handleApplicationError(int, String)} that includes the
	 * resourceId related to the error - critical for knowing when you have a
	 * problem with a resource you created. Default implementation simply calls
	 * {@link #handleApplicationError(int, String)}. ApplicationError codes 1
	 * (e.g. "can't create rsrc. unsupported stream type
	 * /avatar/cf1e61a4330e75d5d1d7a744c5ef38c4") and 3 (e.g. "resource 2091 not
	 * found (type type[-1])") about a resource never provide a resourceinfo
	 * event!
	 * 
	 * @param errorCode
	 *            the error code of the error (one of the {@link IHmeProtocol}
	 *            APP_ERROR_ constants)
	 * @param errorText
	 *            details of the error
	 * @param resourceId
	 *            the id associated with the error - could be null. Suitable for
	 *            use with {@link #getResource(Object)} (or ((WeakReference)
	 *            {@link #getResources()}.get(Object)).get() to avoid automatic
	 *            SDK warning message when it's not found)
	 * @return true if the event was handled.
	 */
	public boolean handleApplicationError(int errorCode, String errorText, Integer resourceId) {
		if (handleApplicationError(errorCode, errorText)) {
			return true;
		} else {
			// FIXME add processing needed by e.g. image exceeding max width or
			// height (errorCode 2) with no resource id
			return false;
		}
	}

	/**
	 * Perform some common handling - be sure to call this from subclasses that
	 * override it. Sets {@link #tivoVersion} from DEVICE_INFO. Improves error
	 * handling by posting resource errors to the resource itself, and calling
	 * {@link #handleApplicationError(int, String, Integer)}, passing in
	 * resource ID.
	 * 
	 */
	public boolean handleEvent(HmeEvent event) {
		// get tivo version from device info
		if (event.getOpCode() == EVT_DEVICE_INFO) {
			HmeEvent.DeviceInfo info = (DeviceInfo) event;
			this.tivoVersion = (String) info.getMap().get("version"); //$NON-NLS-1$
			// com.tivo.examine.idType.stationId=tivo,
			// platform=Gen06,
			// host=Bedroom,
			// brand=TiVo,
			// com.tivo.examine.showing=true,
			// com.tivo.examine.idType.contentId=tivo,
			// version=11.0k-01-2-652
		}
	
		// ...
		if (event.getOpCode() == EVT_APP_INFO) {
			HmeEvent.ApplicationInfo info = (HmeEvent.ApplicationInfo) event;
			if (info.getMap().get("error.code") != null) { //$NON-NLS-1$
				int errorCode = Integer.parseInt((String) info.getMap().get(
						"error.code")); //$NON-NLS-1$
				Integer resourceId = null;
				if (info.getMap().get("error.rsrc") != null) { //$NON-NLS-1$
					try {
						resourceId = new Integer((String) info.getMap().get(
								"error.rsrc")); //$NON-NLS-1$
					} catch (NumberFormatException e) {
						resourceId = null;
					}
				}
				String errorText = (String) info.getMap().get("error.text"); //$NON-NLS-1$
				if (resourceId != null) {
					WeakReference res_wr = (WeakReference) getResources().get(
							resourceId);
					if (res_wr != null && res_wr.get() != null) {
						Resource res = (Resource) res_wr.get();
						Map resInfoMap = info.getMap();
						// TODO we're doing this regardless of whether it's
						// actually a change in status
						if (res.status == Resource.RSRC_STATUS_ERROR) {
							debug("NOTE: had to send ResourceStatus event for error even though resource's status was already error."); //$NON-NLS-1$
						}
						debug("Posting APP_INFO resource error to resource " //$NON-NLS-1$
								+ resourceId + ": " + resInfoMap); //$NON-NLS-1$
						res.postEvent(new MockResourceStatus(resourceId
								.intValue(), res, Resource.RSRC_STATUS_ERROR,
								resInfoMap));
					}
				} else
					debug("APP_INFO error " + errorCode + ": " + errorText); //$NON-NLS-1$ //$NON-NLS-2$
	
				return handleApplicationError(errorCode, errorText, resourceId);
			}
		}
	
		boolean result = super.handleEvent(event);
		// ...
	
		return result;
	}

	/**
	 * SDK Bug Fix - OMG! sick bug in HMEObject that has never been noticed or
	 * exercised since nobody has apparently attempted to do App-in-app with
	 * {@link #createStream(String, Map)}. They forgot a "new" keyword and
	 * auto-"fixed" the problem creating a method named LinkedHashMap that has
	 * default method content returning null! Also, calling code won't handle
	 * the nulls that are returned in certain circumstances, so now returning an
	 * empty map here. Lucky for us it is public and non-final. {@inheritDoc}
	 * 
	 * @see com.tivo.hme.sdk.HmeObject#parseQuery(java.lang.String)
	 */
	public Map parseQuery(String query) {
		Map map = new LinkedHashMap();
		if (query == null || query.indexOf('=') == -1) {
			return map;
		}
	
		int at = 0;
		int len = query.length();
	
		if (query.startsWith("?")) { //$NON-NLS-1$
			++at;
		}
		do {
			// find = and &
			int equal = query.indexOf('=', at);
			if (equal < 0) {
				throw new IllegalArgumentException(
						"invalid query (trailing key, = not found)"); //$NON-NLS-1$
			}
			int amp = query.indexOf('&', equal);
			if (amp == -1) {
				amp = query.length();
			}
	
			// add the key/value
			try {
				String key = URLDecoder.decode(query.substring(at, equal),
						"UTF-8"); //$NON-NLS-1$
				String value = URLDecoder.decode(
						query.substring(equal + 1, amp), "UTF-8"); //$NON-NLS-1$
				map.put(key.toLowerCase(), value);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
	
			// advance
			at = amp + 1;
		} while (at < len);
		return map;
	}

	/* END fix JDK */

	/**
	 * Override to handle additional system font ids as [id].ttf and additional
	 * names.
	 */
	public Resource createTrueType(String family) {
		// automatically handle 10.ttf - 19.ttf as ID refs
		if (family != null && family.matches("\\d+\\.ttf")) {
			try {
				int id = Integer.parseInt(family.substring(0, family.length()-4));
				if (id < 20 && id >= 10) {
					return new TrueTypeFalseResource(this, family, id);
				}
				if(id >= 20) {
					return getResource(new Integer(id));
				}
			} catch (Exception e) {
			}
		}
		// handle specific new names
		if (family.equals(TTF_SERIES4FONT)) {
			return new TrueTypeFalseResource(this, family, 13);
		} else if (family.equals(TTF_SERIES4FONTITALIC)) {
			return new TrueTypeFalseResource(this, family, 14);
		} else if (family.equals(TTF_SERIES4FONT3BOLD)) {
			return new TrueTypeFalseResource(this, family, 15);
//		} else if... {
		} else {
			// default behavior
			return super.createTrueType(family);
		}
	}

	/**
	 * Equivalent of TrueTypeResource except accessible to this class so we can
	 * instantiate additional names with a supplied id
	 */
	private static class TrueTypeFalseResource extends Resource {
		String name;

		TrueTypeFalseResource(Application app, String name, int id) {
			super(app, id);
			this.name = name;
			((V49BApplication)app).debug("Created font " + name + " with id " + id);
		}

		/**
		 * This is a thread-safe public entry point.
		 */
		protected void toString(StringBuffer buf) {
			synchronized (lock) {
				buf.append(",ttf=" + name);
			}
		}
	}
	
	
	private boolean waitingToInit;

	@Override
	protected void setContext(IContext context, int version) {
		super.setContext(context, version);
		// make accessible version of private Application class variable.
		this.protocolVersion = version;
		debug("Protocol Version per TiVo DVR: " + protocolVersion); //$NON-NLS-1$
	
		debug("attributes: " + context.getConnectionAttributes()); //$NON-NLS-1$
		// User-Agent: TvHttpClient -my tivo (and tsn=64...3E )
		// User-Agent: TmkHttpRequest/1.0 - from somebody on internet - old
		// version of tivo?
		// User-Agent=tivo.http/03/30/2003 - simulator
		// attributes: {Cookie=id=895df24b5038b953631128d3aa994863d51da2b1,
		// Host=192.168.0.20:7288, User-Agent=TvHttpClient, Connection=close,
		// tsn=64...3E}
		this.tivoID = context.getConnectionAttribute("tsn"); //$NON-NLS-1$
		// context.getConnectionAttribute(HTTP_HEADER_TIVO_ID);
		// tivoVersion is in DEVICE_INFO event under "version"
		// this.tivoVersion =
		// context.getConnectionAttribute(HTTP_HEADER_TIVO_VERSION);
	
	}

	/**
	 * You should override {@link #initBeforeResolutionSet(IContext)} to do your
	 * init work while this override handles resolution details after that is
	 * called.
	 */
	@Override
	public void init(IContext context) throws Exception {
		super.init(context);
		setActive(true);
		
		// template method for subclasses to perform init activities
		initBeforeResolutionSet(context);
		
		waitingToInit = true;
		boolean changed = setPreferredResolution();
		// will continue init on rootBoundsChanged()
	
		this.setActive(true);
	
		if (!changed || !isResolutionSupported()) {
			waitingToInit = false;
			showFirstPage();
		}

	}

	/**
	 * This override coordinates with the {@link #init(IContext)} override to
	 * call {@link #showFirstPage()} at the right time. Should probably override
	 * {@link #rootBoundsChangedBeforeFirstPage(Rectangle)} instead of this to
	 * maintain order of calls.
	 */
	@Override
	public void rootBoundsChanged(Rectangle rootBounds) {
		super.rootBoundsChanged(rootBounds);
		
		// template method for subclasses to perform rootbounds activities? maybe just subclass calling super is good enough here.
		rootBoundsChangedBeforeFirstPage(rootBounds);
		
		if (isResolutionSupported()) {
			if (waitingToInit) {
				waitingToInit = false;
				showFirstPage();
			}
		}
	}

	/**
	 * Resolution control is supported in protocol version 0.43 and SDK 1.4.1
	 */
	public boolean isResolutionSupported() {
		return this.protocolVersion >= VERSION_0_43 && isSDK141();
	}

	/**
	 * Stream Map argument is supported in protocol version 0.45 and SDK 1.4.1
	 */
	public boolean isStreamMapSupported() {
		return this.protocolVersion >= VERSION_0_45 && isSDK141();
	}

	/**
	 * Slide Remote is supported in protocol version 0.49
	 */
	public boolean isSlideRemoteSupported() {
		return this.protocolVersion >= VERSION_0_49;
	}

	/**
	 * Tries to get the version string from the com.tivo.hme.sdk.Version class
	 * which doesn't exist in all SDK versions. Returns null if it can't find
	 * the class.
	 * 
	 * @return
	 */
	public static String getSDKVersion() {
		try {
			if (Class.forName("com.tivo.hme.sdk.Version") != null) //$NON-NLS-1$
				return Version.getVersion();
			else
				return null;
		} catch (ClassNotFoundException e) {
			return null;
		}
	}

	public static boolean isSDK141() {
		if (getSDKVersion() != null)
			return getSDKVersion().startsWith("1.4.1"); //$NON-NLS-1$
		else
			return false;
	}

	/** a multi-SDK version of the SDK 1.4.1 method */
	public int getSafeActionHorizontal() {
		if (!isSDK141()) {
			return SAFE_ACTION_H;
		} else {
			return super.getSafeActionHorizontal();
		}
	}

	/** a multi-SDK version of the SDK 1.4.1 method */
	public int getSafeTitleVertical() {
		if (!isSDK141()) {
			return SAFE_TITLE_V;
		} else {
			return super.getSafeTitleVertical();
		}
	}

	/** a multi-SDK version of the SDK 1.4.1 method */
	public int getSafeActionVertical() {
		if (!isSDK141()) {
			return SAFE_ACTION_V;
		} else {
			return super.getSafeActionVertical();
		}
	}

	/** a multi-SDK version of the SDK 1.4.1 method */
	public int getSafeTitleHorizontal() {
		if (!isSDK141()) {
			return SAFE_TITLE_H;
		} else {
			return super.getSafeTitleHorizontal();
		}
	}

	
	/** Standard title area for e.g. a STREAM_LOOP_* background. */
	public Rectangle getTitleRegion() {
		int topPad = getSafeTitleVertical();
		int height = getSafeTitleToScrollTop()
				- 15;
		int leftPad = getSafeTitleHorizontal() + getSafeLogoToScrollTitle();
		int rightPad = getSafeTitleHorizontal();
		return new Rectangle(leftPad, topPad, getWidth()-leftPad-rightPad, height);
	}
	
	/** Standard logo area for e.g. a STREAM_LOOP_* background. */
	public Rectangle getLogoRegion() {
		int topPad = getSafeTitleVertical();
		int height = getSafeTitleToScrollTop()
				- 15;
		int leftPad = getSafeTitleHorizontal()
				- 20;
		int width = getSafeLogoToScrollTitle() + 10; // seems to fit, but shouldn't it be +20 to offset leftpad adjustment?
		return new Rectangle(leftPad, topPad, width, height);
	}

	/** Standard scroll area for e.g. a STREAM_LOOP_* background. */
	public Rectangle getScrollRegion() {
		int bottomPad = getSafeTitleVertical()+getSafeTitleToScrollBottom();
		int topPad = getSafeTitleVertical()+getSafeTitleToScrollTop();
		int leftPad = getSafeTitleHorizontal();
		int rightPad = getSafeTitleHorizontal();
		return new Rectangle(leftPad, topPad, getWidth()-leftPad-rightPad, getHeight()-topPad-bottomPad);
	}
	
	/**
	 * Vertical Space from safeTitle bottom to bottom of scrolling area of of a
	 * STREAM_LOOP_* background.
	 */
	public int getSafeTitleToScrollBottom() {
		if (isResolutionSupported() && getCurrentResolution().getHeight() > 480) {
			return 30;
		} else {
			return 15; // SD number
		}
	}

	/**
	 * Vertical Space from safeTitle top to top of scrolling area of a
	 * STREAM_LOOP_* background.
	 */
	public int getSafeTitleToScrollTop() {
		if (isResolutionSupported() && getCurrentResolution().getHeight() > 480) {
			return 85 + 60;
		} else {
			return 95; // SD number
		}
	}
	
	/**
	 * Horizontal space from safeTitle left to right edge of TiVo logo in the
	 * title area of a STREAM_LOOP_* background.  Note, logo extends a little to the left of the safeTitle left.
	 */
	public int getSafeLogoToScrollTitle() {
		if (isResolutionSupported() && getCurrentResolution().getHeight() > 480) {
			return 100; // could need a diff number for 720, but this will work.
		} else {
			return 45;// SD number - goes past "glow"
		}
	}
	
	protected void setMaxStackDepth(int max) {
		if (isSDK141()) {
			super.setMaxStackDepth(max);
		}
	}

	/**
	 * If {@link #isResolutionSupported()}, makes sure the resolution is the
	 * preferred one, and if it's not, calls
	 * {@link #setReceiverResolution(com.tivo.hme.sdk.Resolution)} with the
	 * ResolutionInfo's preferred resolution.
	 * 
	 * @return true if {@link #setReceiverResolution(com.tivo.hme.sdk.Resolution)} was actually called.
	 */
	protected boolean setPreferredResolution() {
			/* BEGIN HME 1.4.1e only */
			if (isResolutionSupported()) {
				boolean noChangeNeeded = this
						.getReceiverResolutionInfo()
						.getPreferredRenderingResolution()
						.equals(this.getReceiverResolutionInfo()
								.getRenderingResolution());
				if (noChangeNeeded) {
	//				debugOut(this.getCurrentResolution()+" is already preferred resolution of "+this.getReceiverResolutionInfo().getAvailableRenderingResolutions());
					return false;
				} else {
	//				 debugOut(this.getCurrentResolution()
	//						 +" => "+this.getReceiverResolutionInfo().getPreferredRenderingResolution()+" of "+this.getReceiverResolutionInfo().getAvailableRenderingResolutions());
					this.setReceiverResolution(this.getReceiverResolutionInfo()
							.getPreferredRenderingResolution());
					return true;
				}
			}
			/* END HME 1.4.1e only */
			return false;
		}

}
V49BApplicationFactory.java:
Code:
package com.blackledge.david.tivo;

import java.io.IOException;

import com.tivo.hme.interfaces.IApplication;
import com.tivo.hme.interfaces.IContext;
import com.tivo.hme.interfaces.ILogger;
import com.tivo.hme.sdk.Factory;
import com.tivo.hme.sdk.IHmeProtocol;
import com.tivo.hme.sdk.io.HmeInputStream;
import com.tivo.hme.sdk.io.HmeOutputStream;

/**
 * Factory that creates the {@link V49BApplication} to report its version to the
 * TiVo as VERSION_0_49. (V49BApplication required for createApplication
 * duplicate to have correct method access).
 */
public class V49BApplicationFactory extends Factory {
	/**
	 * Override to report a different HME version by calling
	 * {@link #supercreateApplication(IContext, int)}.
	 */
	@Override
	public IApplication createApplication(IContext context)
			throws IOException {
        int sentVersion = 
//                IHmeProtocol.VERSION;
        		V49IHmeProtocol.VERSION_0_49;
//        		IHmeProtocol.VERSION_0_40;
        
		IApplication application = supercreateApplication(context, sentVersion);
		
		return application;
	}
	
	/**
	 * Copy of super factory implementation with parameterized version number to
	 * send to TiVo.
	 */
    public IApplication supercreateApplication(IContext context, int sentVersion) throws IOException
    {
	int version = -1;
        HmeOutputStream out = null;
        HmeInputStream in = null;

        synchronized (lock) {                   // lock this factory
            if (context.getOutputStream() instanceof HmeOutputStream) {
                out = (HmeOutputStream)context.getOutputStream();
	    }
            else {
                out = new HmeOutputStream(context.getOutputStream());
	    }
            
            if (context.getInputStream() instanceof HmeInputStream) {
                in = (HmeInputStream)context.getInputStream();
            } else {
                in = new HmeInputStream(context.getInputStream());
	    }
            
            // HME protocol starts here
	    // Synchronize and flush the writes, so that no other writer 
	    // interleaves within our data
	    synchronized (out.getMonitor()) {
                out.writeInt(IHmeProtocol.MAGIC);
                out.writeInt(
//                		IHmeProtocol.VERSION
                		sentVersion
                		);
                out.flush();
	    }
		
            // read magic and version
            int magic = in.readInt();
            if (magic != IHmeProtocol.MAGIC) {
                throw new IOException(
		    "bad magic: 0x" + Integer.toHexString(magic)
//		    +getIdForException());
		    );
            }
            version = in.readInt();
            if (version >> 8 < 
//            IHmeProtocol.VERSION
            sentVersion
            >> 8 ) {
                throw new IOException(
                        "version mismatch: " + 
                        ( version >> 8 ) + "." + ( version & 0xff ) +
                        " < " +
                        ( 
//                        		IHmeProtocol.VERSION
                        		sentVersion
                        		>> 8 ) + "." + ( 
//                        				IHmeProtocol.VERSION
                        				sentVersion
                        				& 0xff )
//			+ getIdForException());
                        );
            }
        } // synchronized

        // maintain proper order of locks -- we have released 
        // the factory monitor before entering the app monitor
    
        IApplication retApp = null;
        try {
//            Application app = (Application)clazz.newInstance();
        	// have to have local class to access setContext
        	V49BApplication app = (V49BApplication)clazz.newInstance();
            synchronized (app) {
                app.setFactory(this);
                app.setContext(context, version);
		app.setMonitor(app);
                retApp = app;
            }
        } catch (InstantiationException ex) {
	    log(ILogger.LOG_NOTICE, ex);
        } catch (IllegalAccessException ex) {
	    log(ILogger.LOG_NOTICE, ex);
        }

	out.flush();

        return retApp;
    } // createApplication()
	
}

__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-01-2013, 11:22 PM   #69
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Arrow Enter Webz server @ 212.1.209.140

After the overwhelming lack of interest in the last update, I just went forward with the cheapest host I could come up with for a beta of a public server.

"Add a server" or "Add an app" with IP 212.1.209.140

This will add Enter Webz in server mode. This means the Apps group drives what specific links or groups show up as "apps" at the top level on your TiVo.

The default thumztaks give you a lot of top-level Apps. They use genres so in Series 4+ HD UIs, some Apps are in the music and photos section while other entries are in the apps section. Default icons are also based on genres.
  • music: Shoutcast Radio Stations
  • music: Live Concerts at archive.org
  • music: M​ore/ (last.fm, Audio Books, MP3tunes)​
  • photos: Comics & LOLz/
  • photos: Flickr
  • videos: Feature Films at archive.org
  • videos: YouTube mobile
  • videos: ​More/ (Classic TV, Amazon download launch, late night lineups...)
  • Facebook
  • Twitter ​ -​ ​@​TiVo ​ (won't allow connection??)​
  • Email, Finance, etc./ (Google mail / voice, Mapquest, E*Trade...)
  • Sports & Weather/
  • ​Shopping/ (Amazon, Ebay...)
As a bonus, the server also has my Solitaire, Freecell, and Gene Wadleigh's Mahjongg.


THIS IS STILL A BETA - If you wander to random websites it WILL reboot your TiVo in all likelihood, but the default listed ones seem to work well. This problem won't change in the future, but I hope to put warnings and safeguards up.
Don't be surprised if it goes down or gets slow if this somehow becomes popular. If I find the need to upgrade the server, the IP Address WILL CHANGE.
And in general, there's still a lot to do to have this feel vaguely like quality.


Today's version includes image size and textarea bug fixes (necessary for e.g. Facebook and twitter status updates)

One problem: it looks like Twitter blocks my host - I'm guessing spammers must have set up shop there, too - so Twitter just times out and never connects. I'll try to contact them to make an exception for my IP, I guess.

Note the "Amazon download launch" mentioned above - that's the "Amazon: Your Video Library" page to initiate a push from an old Amazon video purchase to one of your TiVos... it's not pretty, but I believe it's functional.
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-02-2013, 07:24 AM   #70
Fofer
༺♥༻
 
Fofer's Avatar
 
Join Date: Oct 2000
Location: Neither here nor there
Posts: 69,895
TC CLUB MEMBER
Sounds great! Can't wait to try it when I get back home!
__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
- a list of some favorite browser add-ons that help make TCF even more enjoyable!
Fofer is offline   Reply With Quote
Old 12-02-2013, 10:49 AM   #71
dadrepus
Registered User
 
dadrepus's Avatar
 
Join Date: Jan 2012
Posts: 65
Just tried it. Only tried established programs/games but EVERYTHING worked as promised. From my Mac install to boot! YEA. Can't wait to see what more you have in mind for this clever Application.
thanks for continuing to pursue this.
dadrepus is offline   Reply With Quote
Old 12-02-2013, 02:24 PM   #72
jgametest
Registered User
 
Join Date: Oct 2013
Posts: 117
Lightbulb Looking Forward. =)

Sent David a PM via his email, there is much potential for what his app will bring to the community now that it's being hosted live via IP. It kind of picks up where apps.tv left off but in a whole new direction of hope. I would imagine once the Opera SDK gets off then more opportunity will arise. Now if only I can get his browser to talk to my Plex server I would be very happy. I forced my Plex to use the Opera browser in TiVo through KMTTG and it did it even let me sign into it but would not let me navigate anywhere. I will have to try this idea again this time using Enterthewebz.
jgametest is offline   Reply With Quote
Old 12-02-2013, 04:34 PM   #73
Fofer
༺♥༻
 
Fofer's Avatar
 
Join Date: Oct 2000
Location: Neither here nor there
Posts: 69,895
TC CLUB MEMBER
Quote:
Originally Posted by dadrepus View Post
Just tried it. Only tried established programs/games but EVERYTHING worked as promised. From my Mac install to boot! YEA.
"Mac install?" Why is that needed, now that it is hosted live via IP? I thought the whole point of that upgrade is that we don't need any software installed (or server hosted) on our LAN.
__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
- a list of some favorite browser add-ons that help make TCF even more enjoyable!
Fofer is offline   Reply With Quote
Old 12-02-2013, 04:56 PM   #74
wmcbrine
Resistance Useless
 
wmcbrine's Avatar
 
Join Date: Aug 2003
Posts: 9,076
Quote:
Originally Posted by davidblackledge View Post
212.1.209.140
1. How do you do the purple box around each menu item?
2. How can I turn that off?
__________________

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
wmcbrine is offline   Reply With Quote
Old 12-02-2013, 05:26 PM   #75
jgametest
Registered User
 
Join Date: Oct 2013
Posts: 117
Red face feedback from shoutcast pending

With Winamp closing it's doors at the end of the month it's unsure what will happen to the @Shoutcast servers. I sent a tweet to the NY office to find out the details apparently many companies rely on this feed of Mp3's.

With IP binded I found new choices in my Music category: More music, Shoutcast, and Concerts.

On a different note, the TiVo played POP & Seasonal very clear. =)
Lookout Pandora more options are coming, the same threat Live365 felt when Pandora arrived.
jgametest is offline   Reply With Quote
Old 12-02-2013, 08:00 PM   #76
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by jgametest View Post
It kind of picks up where apps.tv left off but in a whole new direction of hope.
Yeah, that was kind of my thought, too!
Quote:
Originally Posted by jgametest View Post
Now if only I can get his browser to talk to my Plex server I would be very happy. I forced my Plex to use the Opera browser in TiVo through KMTTG and it did it even let me sign into it but would not let me navigate anywhere. I will have to try this idea again this time using Enterthewebz.
Well, here's where we run into the downside of a public server. Your Plex server is on your home network, behind a firewall that the Enter Webz public server can't see through. Same issue with pyTivo running on your home network.

I plan to make a diagram and a simple website for Enter Webz to explain this kind of stuff.
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-02-2013, 08:01 PM   #77
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by Fofer View Post
"Mac install?" Why is that needed, now that it is hosted live via IP? I thought the whole point of that upgrade is that we don't need any software installed (or server hosted) on our LAN.
You are correct... I think dadrepus was just excited because we could never get the download to work on his Mac ;]
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-02-2013, 08:13 PM   #78
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by wmcbrine View Post
1. How do you do the purple box around each menu item?
2. How can I turn that off?
I love to surprise wmcbrine ;]

It ends up, the HDUI handles app icons differently than they used to.
An incorrectly sized icon on Series 3 either shows nothing or just centers and crops to size.
The HDUI tries to show the whole thing aligned to the upper left corner, regardless of the size. This makes for some messy results for some websites where Enter Webz grabs an iPad-style icon that's very large, but inspired me to do this trick.

The purple box is an experimental Premiere-(and Roamio?)-only icon set sized carefully to fit the App title with a transparent area to let the title show through.

I'll eventually replace that with either a normal icon or a more subtle use of the trick.

It only has that for "other" genre thumztaks (without their own icon) and groups, so you can "turn it off" by deleting those entries or moving them to the video genre.

I also intend to eventually make the thumztak icon user-editable so you can set it if it's blank, or fix it if it's an oversized one. That doesn't include groups, though.
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-03-2013, 05:48 AM   #79
jgametest
Registered User
 
Join Date: Oct 2013
Posts: 117
Can you simulate FLASH playback?

There is an open player called flowplayer it makes flash available from your own site. Could this be adopted into Webz or does it need the Opera SDK active for use?

flowplayerDOTorg <-- replace dot with a .
jgametest is offline   Reply With Quote
Old 12-03-2013, 09:02 PM   #80
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by jgametest View Post
There is an open player called flowplayer it makes flash available from your own site. Could this be adopted into Webz or does it need the Opera SDK active for use?

flowplayerDOTorg <-- replace dot with a .
Well, Enter Webz won't ever run Flash. But the rest of that site uses the HTML5 VIDEO tag which Enter Webz does handle. A VIDEO tag with the right format of video is shown in Enter Webz with either a "poster" image or (in the case of that site) a default video icon.

The videos on that site appear to be an incompatible format of mp4, but other than that, it "works."
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-04-2013, 05:40 AM   #81
jgametest
Registered User
 
Join Date: Oct 2013
Posts: 117
Doing a double-take

David, I've advised the TCM community to take a look at your IP project. yesterday Google released an updated youtube app and seems to be making everyone see RED. It's not an easy monster to navigate and it seems to not want to play many video formats. Whereas your EntertheWebz does it seems a nicer tradeoff vs. do what now? What do you mean I forgot to hit go back to get up left right PLAY something. No it's really not engineered using KISS it's more like KISSOFF.

http://www.tivocommunity.com/tivo-vb...d.php?t=512002
jgametest is offline   Reply With Quote
Old 12-04-2013, 08:42 PM   #82
steinbch
Registered User
 
steinbch's Avatar
 
Join Date: Nov 2007
Posts: 83
Pretty neat implementation. Thanks!

Is there a way to remove the whole thing though? All the apps stayed after a restart and resetting the HDUI. Can't find a way to remove all of the apps or the IP from TiVos memory.
steinbch is offline   Reply With Quote
Old 12-04-2013, 10:33 PM   #83
jgametest
Registered User
 
Join Date: Oct 2013
Posts: 117
Note How to Remove add on Apps

Highlight the app you wish to remove and hit CLEAR answer the question to remove.
jgametest is offline   Reply With Quote
Old 12-05-2013, 07:42 AM   #84
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Dpm

Quote:
Originally Posted by steinbch View Post
Pretty neat implementation. Thanks!

Is there a way to remove the whole thing though? All the apps stayed after a restart and resetting the HDUI. Can't find a way to remove all of the apps or the IP from TiVos memory.


Alternatively, you can customize it:
Start the Enter Webz" entry at the bottom, select the "Apps" group, and either:
use Thumbs Down ( ) to remove entries you don't want any more
OR
use Enter to edit an entry and move it to a group other than "Apps"

That will reduce you to just a few permanent entries

(ack... my keyboard went crazy right at the end and I can't edit the title now :/ the title was supposed to say "Don't remove the whole thing, customize!")
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.

Last edited by davidblackledge : 12-05-2013 at 07:44 AM. Reason: title
davidblackledge is offline   Reply With Quote
Old 12-05-2013, 10:34 AM   #85
steinbch
Registered User
 
steinbch's Avatar
 
Join Date: Nov 2007
Posts: 83
Thanks! Will try it out tonight. Thanks for all of your developmental efforts!
steinbch is offline   Reply With Quote
Old 12-05-2013, 09:27 PM   #86
steinbch
Registered User
 
steinbch's Avatar
 
Join Date: Nov 2007
Posts: 83
I went and tried both methods (using Clear button in TiVo Central and using Thumbs Down while in Webz interface). Both of these have caused issues for me.

Using the Clear button while in TiVo Central removed all of the Webz apps located in SHowcases & Apps, but did not remove any of the extra apps in Music & Photos. Adding Webz again and clearing for a second time removed ALL apps, including those from TiVo from showing up in Showcases & Apps menu.

Using the Thumbs Down option worked while in the Webz interface, but as soon as I exted the Webz App, nothing changed in TiVo Central and returning to the Webz interface showed that no changes were saved.

Thoughts?
steinbch is offline   Reply With Quote
Old 12-05-2013, 10:22 PM   #87
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by steinbch View Post
I went and tried both methods (using Clear button in TiVo Central and using Thumbs Down while in Webz interface). Both of these have caused issues for me.

Using the Clear button while in TiVo Central removed all of the Webz apps located in SHowcases & Apps, but did not remove any of the extra apps in Music & Photos. Adding Webz again and clearing for a second time removed ALL apps, including those from TiVo from showing up in Showcases & Apps menu.

Using the Thumbs Down option worked while in the Webz interface, but as soon as I exted the Webz App, nothing changed in TiVo Central and returning to the Webz interface showed that no changes were saved.

Thoughts?
Sorry, I should have explained that with the original IP server post.

The Premiere and above TiVos remember the list of apps so it doesn't take forever to show the list like it does on TiVo HD and below.

For editing the list from Enter Webz, this becomes a problem. I have set it to expire after 5 minutes, but the TiVo doesn't even check the expiration unless you leave the top UI.

If you go to your Show list and come back (and 5 minutes have passed since the TiVo last loaded the App List), it should reload fine.

The balancing act is that it takes forever to load that list, but you want it as current as possible. I actually don't like the 5 minute setting I currently use - once you're happy with your app list, you don't want to have a long load time every time you come back from your show list. I'll probably increase the time limit and add a note when you change something in the Apps folder "your changes will appear in about N minutes."

As for the "clear" app delete, I guess the Music & Photos area just doesn't notice when you delete the App, but it should disappear from there after a leave/come back type of reload.

... as for the changes not being there when you got back into the Apps folder, two possibilities. One: if you deleted EVERY ONE of the bookmarks, then it re-filled them with the defaults (ones that aren't in the Apps folder won't get in your way so they don't need to be deleted). Two: weird timing vs. when you did the "clear" delete might have caused the defaults to be loaded again.
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Old 12-08-2013, 04:50 PM   #88
steinbch
Registered User
 
steinbch's Avatar
 
Join Date: Nov 2007
Posts: 83
Quote:
Originally Posted by davidblackledge View Post
Sorry, I should have explained that with the original IP server post.

The Premiere and above TiVos remember the list of apps so it doesn't take forever to show the list like it does on TiVo HD and below.

For editing the list from Enter Webz, this becomes a problem. I have set it to expire after 5 minutes, but the TiVo doesn't even check the expiration unless you leave the top UI.

If you go to your Show list and come back (and 5 minutes have passed since the TiVo last loaded the App List), it should reload fine.

The balancing act is that it takes forever to load that list, but you want it as current as possible. I actually don't like the 5 minute setting I currently use - once you're happy with your app list, you don't want to have a long load time every time you come back from your show list. I'll probably increase the time limit and add a note when you change something in the Apps folder "your changes will appear in about N minutes."

As for the "clear" app delete, I guess the Music & Photos area just doesn't notice when you delete the App, but it should disappear from there after a leave/come back type of reload.

... as for the changes not being there when you got back into the Apps folder, two possibilities. One: if you deleted EVERY ONE of the bookmarks, then it re-filled them with the defaults (ones that aren't in the Apps folder won't get in your way so they don't need to be deleted). Two: weird timing vs. when you did the "clear" delete might have caused the defaults to be loaded again.
Thanks for the information. I let it go over night after removing and it looks like all the apps cleared like I expected.
steinbch is offline   Reply With Quote
Old 12-16-2013, 12:37 PM   #89
jgametest
Registered User
 
Join Date: Oct 2013
Posts: 117
Facebook Mobile

While it's nice to be able to access my facebook account and click on the photos to show the kids, I noticed there is no way to go into the next image without hitting the LEFT arrow on the remote to click on another image. In some instances this would cause "EntertheWebz" to force exit back to Tivo Main. Does it matter if I used the settings to adjust to maximum vs. a preset number for size? This option only appears when on a website and hit INFO to access the setting controls.

Also to prevent burn in for prolong use with features such as Shoutcast, might want to consider adding some kind of Screensaver/dimmer control. Some of your featured sites are using an extreme white backgrounds and that can be troublesome for some LCD/Plasma screens.

Other than, was fun to play mahjong and solitaire on Tivo.
jgametest is offline   Reply With Quote
Old 12-16-2013, 07:59 PM   #90
davidblackledge
Registered lÜser
 
davidblackledge's Avatar
 
Join Date: Sep 2008
Location: NM
Posts: 245
Quote:
Originally Posted by jgametest View Post
While it's nice to be able to access my facebook account and click on the photos to show the kids, I noticed there is no way to go into the next image without hitting the LEFT arrow on the remote to click on another image. In some instances this would cause "EntertheWebz" to force exit back to Tivo Main. Does it matter if I used the settings to adjust to maximum vs. a preset number for size? This option only appears when on a website and hit INFO to access the setting controls.
Well, the flow of the facebook app is up to facebook - it is their mobile site and works however they set it up to work. For some reason they chose to make the images not work well as a slideshow type of interface.

The sudden exiting is the TiVo running out of memory or something like that. It will happen with a lot of browsing, especially with lots of images. The TiVo doesn't tell Enter Webz anything to let me protect against that, unfortunately.

Yes, choosing a different font size can affect how well Enter Webz works (in addition to how visible the text is). Sometimes it's better, sometimes worse, depending on how a page is laid out. On my TiVo HD, gmail breaks if I set the font too large, but on some pages with lots of images, a larger font size makes sure less show up on the screen at once, and things work better.

Quote:
Also to prevent burn in for prolong use with features such as Shoutcast, might want to consider adding some kind of Screensaver/dimmer control. Some of your featured sites are using an extreme white backgrounds and that can be troublesome for some LCD/Plasma screens.
Actually, it does do that. When your TiVo tells Enter Webz you haven't touched the remote for some amount of time (I think it's 10 minutes) Enter Webz does one of three things. If you have a video playing it makes it full screen. If you're playing an audio stream, it dims the screen by to about 90%. If you're not doing either, it quits. If you hit any remote button, the TiVo says you're not idle (and if the screen is dimmed, Enter Webz un-dims it) and the timer starts over.

There is also a separate "dimmer" feature that I haven't finished in Enter Webz. If you turn that on from the "info" menu, it slightly dims the screen for those bright white pages, but currently it doesn't stay dimmed when you go to another page. Do you think fixing that feature would be valuable?

Quote:
Other than, was fun to play mahjong and solitaire on Tivo.
Great!
__________________
EnterWebz.tv
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
+ air qual / lightning maps, minesweeper, 1p/2p card games...

To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
David.Blackledge.com Solitaire/FreeCell, Calendar, Map...
hmedev.wikidot.com
To view links or images in signatures your post count must be 10 or greater. You currently have 0 posts.
davidblackledge is offline   Reply With Quote
Reply
Forum Jump




Thread Tools


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Advertisements

TiVo Community
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
vBulletin Skins by: Relivo Media

(C) 2013 Magenium Solutions - All Rights Reserved. No information may be posted elsewhere without written permission.
TiVo® is a registered trademark of TiVo Inc. This site is not owned or operated by TiVo Inc.
All times are GMT -5. The time now is 10:59 PM.
OUR NETWORK: MyOpenRouter | TechLore | SansaCommunity | RoboCommunity | MediaSmart Home | Explore3DTV | Dijit Community | DVR Playground |