Feeds.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "main.h"
  2. #include "Feeds.h"
  3. #include "./util.h"
  4. #include "./defaults.h"
  5. #include <algorithm>
  6. #include <shlwapi.h>
  7. #include "BackgroundDownloader.h"
  8. #include <strsafe.h>
  9. static bool operator == (const RSS::Item &a, const RSS::Item &b)
  10. {
  11. if(a.guid && a.guid[0] && b.guid && b.guid[0])
  12. return !wcscmp(a.guid, b.guid);
  13. if(a.publishDate && b.publishDate)
  14. return a.publishDate == b.publishDate;
  15. if (a.url && a.url[0] && b.url && b.url[0])
  16. return !wcscmp(a.url, b.url);
  17. return a.url == b.url;
  18. }
  19. Channel::Channel()
  20. {
  21. Init();
  22. }
  23. Channel::Channel(const Channel &copy)
  24. {
  25. Init();
  26. operator =(copy);
  27. }
  28. const Channel &Channel::operator =(const Channel &copy)
  29. {
  30. Reset();
  31. Init();
  32. url = _wcsdup(copy.url);
  33. title = _wcsdup(copy.title);
  34. link = _wcsdup(copy.link);
  35. description = _wcsdup(copy.description);
  36. ttl=copy.ttl;
  37. updateTime=copy.updateTime;
  38. lastUpdate=copy.lastUpdate;
  39. autoDownloadEpisodes=copy.autoDownloadEpisodes;
  40. autoDownload=copy.autoDownload;
  41. autoUpdate=copy.autoUpdate;
  42. useDefaultUpdate=copy.useDefaultUpdate;
  43. needsRefresh=copy.needsRefresh;
  44. items=copy.items;
  45. return *this;
  46. }
  47. Channel::~Channel()
  48. {
  49. Reset();
  50. }
  51. void Channel::Init()
  52. {
  53. url =0;
  54. title = 0;
  55. link = 0;
  56. description = 0;
  57. ttl=0;
  58. lastUpdate=0;
  59. autoUpdate = ::autoUpdate;
  60. updateTime = ::updateTime;
  61. autoDownload = ::autoDownload;
  62. autoDownloadEpisodes = ::autoDownloadEpisodes;
  63. useDefaultUpdate=true;
  64. needsRefresh=false;
  65. }
  66. void Channel::Reset()
  67. {
  68. free(url);
  69. free(title);
  70. free(link);
  71. free(description);
  72. }
  73. void Channel::UpdateFrom(const Channel &copy)
  74. {
  75. if (copy.url && copy.url[0])
  76. SetURL(copy.url);
  77. SetTitle(copy.title);
  78. SetLink(copy.link);
  79. SetDescription(copy.description);
  80. if (copy.ttl)
  81. ttl=copy.ttl;
  82. ItemList::const_iterator itr;
  83. for (itr=copy.items.begin();itr!=copy.items.end();itr++)
  84. {
  85. const RSS::Item &b = *itr;
  86. if ( b.url && b.url[0] )
  87. {
  88. ((RSS::Item*)&b)->downloaded = IsPodcastDownloaded(b.url);
  89. }
  90. }
  91. // update to the latest default setting
  92. if (useDefaultUpdate)
  93. {
  94. autoUpdate = ::autoUpdate;
  95. updateTime = ::updateTime;
  96. autoDownload = ::autoDownload;
  97. autoDownloadEpisodes = ::autoDownloadEpisodes;
  98. }
  99. items.clear(); // benski> added for 5.23
  100. for (itr=copy.items.begin();itr!=copy.items.end();itr++)
  101. {
  102. items.insert(items.begin(), *itr);
  103. }
  104. if(autoDownload)
  105. {
  106. SortByDate();
  107. size_t idx = items.size();
  108. if (idx)
  109. {
  110. int episodeCount = 0;
  111. do
  112. {
  113. idx--;
  114. const RSS::Item &b = items[idx];
  115. if(b.url && b.url[0])
  116. {
  117. episodeCount++;
  118. if (!b.downloaded)
  119. {
  120. WCHAR szPath[MAX_PATH *2] = {0};
  121. if (SUCCEEDED(((RSS::Item*)&b)->GetDownloadFileName(title, szPath, ARRAYSIZE(szPath), TRUE)))
  122. {
  123. wchar_t* url = urlencode(b.url);
  124. downloader.Download(url, szPath, title, b.itemName, b.publishDate);
  125. ((RSS::Item*)&b)->downloaded = true;
  126. free(url);
  127. }
  128. }
  129. }
  130. } while (episodeCount<autoDownloadEpisodes && idx);
  131. }
  132. }
  133. }
  134. bool Channel::operator == (const Channel &compare)
  135. {
  136. // changed from basing on the title as this allows for podcasts
  137. // with the same name to still work instead of being mangled as
  138. // was able to happen when this based things on the title value
  139. if (!compare.url || !compare.url[0])
  140. return false;
  141. return !wcscmp(url, compare.url);
  142. }
  143. bool TitleMediaSort(const RSS::Item &item1, const RSS::Item &item2)
  144. {
  145. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, item1.itemName, -1, item2.itemName, -1));
  146. }
  147. void Channel::SortByTitle()
  148. {
  149. std::sort(items.begin(), items.end(), TitleMediaSort);
  150. }
  151. static bool ItemMediaSort(const RSS::Item &item1, const RSS::Item &item2)
  152. {
  153. if (!item1.url || !item1.url[0])
  154. return false;
  155. if (!item2.url || !item2.url[0])
  156. return true;
  157. if (!item2.listened)
  158. return false;
  159. if (item1.listened)
  160. return false;
  161. return true;
  162. }
  163. bool ParseDuration(const wchar_t *duration, int *out_hours, int *out_minutes, int *out_seconds);
  164. static bool ItemMediaTimeSort(const RSS::Item &item1, const RSS::Item &item2)
  165. {
  166. if (!item1.duration || !item1.duration[0])
  167. return false;
  168. if (!item2.duration || !item2.duration[0])
  169. return true;
  170. int h1, h2, m1, m2, s1, s2;
  171. if (!ParseDuration(item1.duration, &h1, &m1, &s1))
  172. return false;
  173. if (!ParseDuration(item2.duration, &h2, &m2, &s2))
  174. return true;
  175. if (h1 < h2)
  176. return true;
  177. else if (h1 > h2)
  178. return false;
  179. if (m1 < m2)
  180. return true;
  181. else if (m1 > m2)
  182. return false;
  183. if (s1 < s2)
  184. return true;
  185. else
  186. return false;
  187. }
  188. static bool ItemMediaSizeSort(const RSS::Item &item1, const RSS::Item &item2)
  189. {
  190. if (!item1.size)
  191. return false;
  192. if (!item2.size)
  193. return true;
  194. return item1.size < item2.size;
  195. }
  196. void Channel::SortByMedia()
  197. {
  198. std::sort(items.begin(), items.end(), ItemMediaSort);
  199. }
  200. void Channel::SortByMediaTime()
  201. {
  202. std::sort(items.begin(), items.end(), ItemMediaTimeSort);
  203. }
  204. void Channel::SortByMediaSize()
  205. {
  206. std::sort(items.begin(), items.end(), ItemMediaSizeSort);
  207. }
  208. bool ItemDateSort(const RSS::Item &item1, const RSS::Item &item2)
  209. {
  210. return (item1.publishDate < item2.publishDate);
  211. }
  212. void Channel::SortByDate()
  213. {
  214. std::sort(items.begin(), items.end(), ItemDateSort);
  215. }
  216. int Channel::GetTitle(wchar_t *str, size_t len)
  217. {
  218. if (str && len)
  219. {
  220. str[0]=0;
  221. if (title && title[0])
  222. StringCchCopyW(str, len, title);
  223. return 0;
  224. }
  225. return 1;
  226. }
  227. void Channel::SetURL(const wchar_t *val)
  228. {
  229. free(url);
  230. url = _wcsdup(val);
  231. }
  232. void Channel::SetTitle(const wchar_t *val)
  233. {
  234. free(title);
  235. title = _wcsdup(val);
  236. }
  237. void Channel::SetLink(const wchar_t *val)
  238. {
  239. free(link);
  240. link = _wcsdup(val);
  241. }
  242. void Channel::SetDescription(const wchar_t *val)
  243. {
  244. free(description);
  245. description = _wcsdup(val);
  246. }
  247. #undef CBCLASS
  248. #define CBCLASS Channel
  249. START_DISPATCH;
  250. CB(IFC_PODCAST_GETTITLE, GetTitle)
  251. END_DISPATCH;
  252. #undef CBCLASS