PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/grawler/TvdbLib/Data/Banner/TvdbBanner.cs

http://grawler.googlecode.com/
C# | 334 lines | 203 code | 22 blank | 109 comment | 28 complexity | 6197059ec5a799695fbfa7cf12878eb5 MD5 | raw file
  1. /*
  2. * TvdbLib: A library to retrieve information and media from http://thetvdb.com
  3. *
  4. * Copyright (C) 2008 Benjamin Gmeiner
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Linq;
  23. using System.Text;
  24. using System.Drawing;
  25. using System.Net;
  26. using System.IO;
  27. using System.Threading;
  28. using TvdbLib.Cache;
  29. namespace TvdbLib.Data
  30. {
  31. /// <summary>
  32. /// Tvdb Banners are the graphical element of tvdb. There are different types of banners which are
  33. /// representet by sub-classes in this library. These subclasses are:
  34. /// <list type="bullet">
  35. /// <item>
  36. /// <term>TvdbEpisodeBanner</term>
  37. /// <description>Each episode may contain a small image that should be an non-spoiler action shot from the episode (http://thetvdb.com/wiki/index.php/Episode_Images)</description>
  38. /// </item>
  39. /// <item>
  40. /// <term>TvdbFanartBanner</term>
  41. /// <description>Fan Art is high quality artwork that is displayed in the background of HTPC menus (http://thetvdb.com/wiki/index.php/Fan_Art)</description>
  42. /// </item>
  43. /// <item>
  44. /// <term>TvdbSeasonBanner</term>
  45. /// <description>Banner for each season of a series, dvd-style (400 x 578) or banner style (758 x 140) (http://thetvdb.com/wiki/index.php/Wide_Season_Banners)</description>
  46. /// </item>
  47. /// <item>
  48. /// <term>TvdbSeriesBanner</term>
  49. /// <description>Wide banner for each series (758 x 140), comes in graphical, text or blank style. For further information see http://thetvdb.com/wiki/index.php/Series_Banners</description>
  50. /// </item>
  51. /// <item>
  52. /// <term>TvdbPosterBanner</term>
  53. /// <description>Newest addition to the tvdb graphical section (680px x 1000px) and not smaller than 500k (http://thetvdb.com/wiki/index.php/Posters)</description>
  54. /// </item>
  55. /// </list>
  56. /// </summary>
  57. [Serializable]
  58. public class TvdbBanner
  59. {
  60. #region private/protected fields
  61. private String m_bannerPath;
  62. private Image m_banner;
  63. private bool m_isLoaded;
  64. private int m_id;
  65. private TvdbLanguage m_language;
  66. private bool m_bannerLoading = false;
  67. private System.Object m_bannerLoadingLock = new System.Object();
  68. private DateTime m_lastUpdated;
  69. private int m_seriesId;
  70. private ICacheProvider m_cacheProvider;
  71. #endregion
  72. /// <summary>
  73. /// Used to load/save images persistent if we're using a cache provider
  74. /// (should keep memory usage much lower)
  75. /// on the other hand we have a back-ref to tvdb (from a data class), which sucks
  76. /// </summary>
  77. public ICacheProvider CacheProvider
  78. {
  79. get { return m_cacheProvider; }
  80. set { m_cacheProvider = value; }
  81. }
  82. /// <summary>
  83. /// Language of the banner
  84. /// </summary>
  85. public TvdbLanguage Language
  86. {
  87. get { return m_language; }
  88. set { m_language = value; }
  89. }
  90. /// <summary>
  91. /// Id of the banner
  92. /// </summary>
  93. public int Id
  94. {
  95. get { return m_id; }
  96. set { m_id = value; }
  97. }
  98. /// <summary>
  99. /// Image data of the banner
  100. /// </summary>
  101. public Image BannerImage
  102. {
  103. get { return m_banner; }
  104. set { m_banner = value; }
  105. }
  106. /// <summary>
  107. /// True if the image data has been already loaded, false otherwise
  108. /// </summary>
  109. public bool IsLoaded
  110. {
  111. get { return m_isLoaded; }
  112. }
  113. /// <summary>
  114. /// Is the banner currently beeing loaded
  115. /// </summary>
  116. public bool BannerLoading
  117. {
  118. get { return m_bannerLoading; }
  119. set { m_bannerLoading = value; }
  120. }
  121. /// <summary>
  122. /// Path to the location on the tvdb server where the image is located
  123. /// </summary>
  124. public String BannerPath
  125. {
  126. get { return m_bannerPath; }
  127. set { m_bannerPath = value; }
  128. }
  129. /// <summary>
  130. /// When was the banner updated the last time
  131. /// </summary>
  132. public DateTime LastUpdated
  133. {
  134. get { return m_lastUpdated; }
  135. set { m_lastUpdated = value; }
  136. }
  137. /// <summary>
  138. /// Id of the series this banner belongs to
  139. /// </summary>
  140. public int SeriesId
  141. {
  142. get { return m_seriesId; }
  143. set { m_seriesId = value; }
  144. }
  145. /// <summary>
  146. /// Loads the actual image data of the banner
  147. /// </summary>
  148. /// <returns>true if the banner could be loaded successfully, false otherwise</returns>
  149. public bool LoadBanner()
  150. {
  151. return LoadBanner(false);
  152. }
  153. /// <summary>
  154. /// Loads the actual image data of the banner
  155. /// </summary>
  156. /// <param name="_replaceOld">If true will replace an old image (if one exists already)</param>
  157. /// <returns>true if the banner could be loaded successfully, false otherwise</returns>
  158. public bool LoadBanner(bool _replaceOld)
  159. {
  160. bool wasLoaded = m_isLoaded;//is the banner already loaded at this point
  161. lock (m_bannerLoadingLock)
  162. {//if another thread is already loading THIS banner, the lock will block this thread until the other thread
  163. //has finished loading
  164. if (!wasLoaded && !_replaceOld && m_isLoaded)
  165. {////the banner has already been loaded from a different thread and we don't want to replace it
  166. return false;
  167. }
  168. m_bannerLoading = true;
  169. if (m_bannerPath.Equals("")) return false;
  170. try
  171. {
  172. Image img = null;
  173. String cacheName = CreateCacheName(m_bannerPath, false);
  174. if (m_cacheProvider != null && m_cacheProvider.Initialised)
  175. {//try to load the image from cache first
  176. img = m_cacheProvider.LoadImageFromCache(m_seriesId, cacheName);
  177. }
  178. if (img == null)
  179. {//couldn't load image from cache -> load it from http://thetvdb.com
  180. img = LoadImage(TvdbLinkCreator.CreateBannerLink(m_bannerPath));
  181. if (img != null && m_cacheProvider != null && m_cacheProvider.Initialised)
  182. {//store the image to cache
  183. m_cacheProvider.SaveToCache(img, m_seriesId, cacheName);
  184. }
  185. }
  186. if (img != null)
  187. {//image was successfully loaded
  188. m_banner = img;
  189. m_isLoaded = true;
  190. m_bannerLoading = false;
  191. return true;
  192. }
  193. }
  194. catch (WebException ex)
  195. {
  196. Log.Error("Couldn't load banner " + m_bannerPath, ex);
  197. }
  198. m_isLoaded = false;
  199. m_bannerLoading = false;
  200. return false;
  201. }
  202. }
  203. /// <summary>
  204. /// Unloads the image and saves it to cache
  205. /// </summary>
  206. /// <returns>true if successful, false otherwise</returns>
  207. public bool UnloadBanner()
  208. {
  209. return UnloadBanner(true);
  210. }
  211. /// <summary>
  212. /// Unloads the image
  213. /// </summary>
  214. /// <param name="_saveToCache">should the image kept in cache</param>
  215. /// <returns>true if successful, false otherwise</returns>
  216. public bool UnloadBanner(bool _saveToCache)
  217. {
  218. if (m_bannerLoading)
  219. {//banner is currently loading
  220. Log.Warn("Can't remove banner while it's loading");
  221. return false;
  222. }
  223. else
  224. {
  225. try
  226. {
  227. if (m_isLoaded)
  228. {
  229. LoadBanner(null);
  230. }
  231. if (!_saveToCache)
  232. {//we don't want the image in cache -> if we already cached it it should be deleted
  233. String cacheName = CreateCacheName(m_bannerPath, false);
  234. if (m_cacheProvider != null && m_cacheProvider.Initialised)
  235. {//try to load the image from cache first
  236. m_cacheProvider.RemoveImageFromCache(m_seriesId, cacheName);
  237. }
  238. }
  239. }
  240. catch (Exception ex)
  241. {
  242. Log.Warn("Error while unloading banner", ex);
  243. }
  244. return true;
  245. }
  246. }
  247. /// <summary>
  248. /// Creates the name used to store images in cache
  249. /// </summary>
  250. /// <param name="_path">Path of the image</param>
  251. /// <param name="_thumb">Is the image a thumbnail</param>
  252. /// <returns>Name used for caching image</returns>
  253. protected String CreateCacheName(String _path, bool _thumb)
  254. {
  255. if (_path.Contains("_cache/"))
  256. {
  257. _path = _path.Replace("_cache/", "");
  258. }
  259. if (_path.Contains("fanart/original/"))
  260. {
  261. _path = _path.Replace("fanart/original/", "fan-");
  262. }
  263. else if (_path.Contains("fanart/vignette/"))
  264. {
  265. _path = _path.Replace("fanart/vignette/", "fan-vig-");
  266. }
  267. _path = _path.Replace('/', '_');
  268. return (_thumb ? "thumb_": "img_") + _path;
  269. }
  270. /// <summary>
  271. /// Loads the banner with the given image
  272. /// </summary>
  273. /// <param name="_img">Image object that should be used for this banner</param>
  274. /// <returns>True if successful, false otherwise</returns>
  275. public bool LoadBanner(Image _img)
  276. {
  277. if (_img != null)
  278. {
  279. m_banner = _img;
  280. m_isLoaded = true;
  281. return true;
  282. }
  283. else
  284. {
  285. m_banner = null;
  286. m_isLoaded = false;
  287. return false;
  288. }
  289. }
  290. /// <summary>
  291. /// Loads the image from the given path
  292. /// </summary>
  293. /// <param name="_path">Path of image that should be used for this banner</param>
  294. /// <returns>True if successful, false otherwise</returns>
  295. protected Image LoadImage(String _path)
  296. {
  297. try
  298. {
  299. WebClient client = new WebClient();
  300. byte[] imgData = client.DownloadData(_path);
  301. MemoryStream ms = new MemoryStream(imgData);
  302. Image img = Image.FromStream(ms, true, true);
  303. return img;
  304. }
  305. catch (Exception ex)
  306. {
  307. Log.Error("Error while loading image ", ex);
  308. return null;
  309. }
  310. }
  311. }
  312. }