| author | Lars Persson <lars.persson@embeddev.se> | 
| Thu, 01 Apr 2010 11:47:56 +0200 | |
| changeset 100 | e0fc52a5df4d | 
| parent 99 | 41d00e97e2f7 | 
| child 102 | 04c6ccce8e7e | 
| permissions | -rw-r--r-- | 
| 2 | 1 | /* | 
| 2 | * Copyright (c) 2007-2010 Sebastian Brannstrom, Lars Persson, EmbedDev AB | |
| 3 | * | |
| 4 | * All rights reserved. | |
| 5 | * This component and the accompanying materials are made available | |
| 6 | * under the terms of the License "Eclipse Public License v1.0" | |
| 7 | * which accompanies this distribution, and is available | |
| 8 | * at the URL "http://www.eclipse.org/legal/epl-v10.html". | |
| 9 | * | |
| 10 | * Initial Contributors: | |
| 11 | * EmbedDev AB - initial contribution. | |
| 12 | * | |
| 13 | * Contributors: | |
| 14 | * | |
| 15 | * Description: | |
| 16 | * | |
| 17 | */ | |
| 18 | ||
| 19 | #include "FeedEngine.h" | |
| 20 | #include <f32file.h> | |
| 21 | #include <bautils.h> | |
| 22 | #include <s32file.h> | |
| 23 | #include "SettingsEngine.h" | |
| 24 | #include "ShowEngine.h" | |
| 25 | #include <e32hashtab.h> | |
| 26 | #include "OpmlParser.h" | |
| 27 | #include "PodcastUtils.h" | |
| 28 | #include <utf.h> | |
| 29 | ||
| 30 | // Cleanup stack macro for SQLite3 | |
| 31 | // TODO Move this to some common place. | |
| 32 | static void Cleanup_sqlite3_finalize_wrapper(TAny* handle) | |
| 33 | 	{
 | |
| 34 | sqlite3_finalize(static_cast<sqlite3_stmt*>(handle)); | |
| 35 | } | |
| 36 | #define Cleanup_sqlite3_finalize_PushL(__handle) CleanupStack::PushL(TCleanupItem(&Cleanup_sqlite3_finalize_wrapper, __handle)) | |
| 37 | ||
| 38 | ||
| 39 | CFeedEngine* CFeedEngine::NewL(CPodcastModel& aPodcastModel) | |
| 40 | 	{
 | |
| 41 | CFeedEngine* self = new (ELeave) CFeedEngine(aPodcastModel); | |
| 42 | CleanupStack::PushL(self); | |
| 43 | self->ConstructL(); | |
| 44 | CleanupStack::Pop(self); | |
| 45 | return self; | |
| 46 | } | |
| 47 | ||
| 48 | void CFeedEngine::ConstructL() | |
| 49 | 	{
 | |
| 50 | iParser = new (ELeave) CFeedParser(*this, iPodcastModel.FsSession()); | |
| 51 | ||
| 52 | iFeedClient = CHttpClient::NewL(iPodcastModel, *this); | |
| 53 | iFeedTimer.ConstructL(); | |
| 54 | ||
| 55 | RunFeedTimer(); | |
| 56 | ||
| 57 | if (DBGetFeedCount() > 0) | |
| 58 |     	{
 | |
| 59 | 		DP("Loading feeds from DB");
 | |
| 60 | DBLoadFeedsL(); | |
| 61 | } | |
| 62 | ||
| 63 | 	if (iPodcastModel.IsFirstStartup()) {
 | |
| 64 | TFileName defaultFile = iPodcastModel.SettingsEngine().DefaultFeedsFileName(); | |
| 65 | 		DP1("Loading default feeds from %S", &defaultFile);
 | |
| 66 | 		if (BaflUtils::FileExists(iPodcastModel.FsSession(), defaultFile)) {
 | |
| 67 | ImportFeedsL(defaultFile); | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | TFileName importFile = iPodcastModel.SettingsEngine().ImportFeedsFileName(); | |
| 72 |     if (BaflUtils::FileExists(iPodcastModel.FsSession(), importFile)) {
 | |
| 73 |     	DP("Importing feeds");
 | |
| 74 | ImportFeedsL(importFile); | |
| 75 | } | |
| 76 | } | |
| 77 | ||
| 78 | CFeedEngine::CFeedEngine(CPodcastModel& aPodcastModel) | |
| 79 | : iClientState(EIdle), | |
| 80 | iFeedTimer(this), | |
| 81 | iPodcastModel(aPodcastModel), | |
| 82 | iDB(*aPodcastModel.DB()) | |
| 83 | 	{
 | |
| 84 | } | |
| 85 | ||
| 86 | CFeedEngine::~CFeedEngine() | |
| 87 | 	{
 | |
| 88 | iObservers.Close(); | |
| 89 | ||
| 90 | iFeedsUpdating.Close(); | |
| 91 | iSortedFeeds.ResetAndDestroy(); | |
| 92 | iSearchResults.ResetAndDestroy(); | |
| 93 | ||
| 94 | delete iParser; | |
| 95 | delete iFeedClient; | |
| 96 | delete iOpmlParser; | |
| 97 | } | |
| 98 | ||
| 99 | /** | |
| 100 | * Returns the current internal state of the feed engine4 | |
| 101 | */ | |
| 102 | EXPORT_C TClientState CFeedEngine::ClientState() | |
| 103 | 	{
 | |
| 104 | return iClientState; | |
| 105 | } | |
| 106 | ||
| 107 | ||
| 108 | /** | |
| 109 | * Returns the current updating client UID if clientstate is != ENotUpdateing | |
| 110 | * @return TUint | |
| 111 | */ | |
| 112 | EXPORT_C TUint CFeedEngine::ActiveClientUid() | |
| 113 | 	{
 | |
| 114 | if(iActiveFeed != NULL) | |
| 115 | 		{
 | |
| 116 | return iActiveFeed->Uid(); | |
| 117 | } | |
| 118 | return 0; | |
| 119 | } | |
| 120 | ||
| 121 | void CFeedEngine::RunFeedTimer() | |
| 122 | 	{
 | |
| 123 | iFeedTimer.Cancel(); | |
| 124 | ||
| 125 | if (iPodcastModel.SettingsEngine().UpdateAutomatically() != EAutoUpdateOff) | |
| 126 | 		{
 | |
| 127 | TInt interval = iPodcastModel.SettingsEngine().UpdateFeedInterval(); | |
| 128 | ||
| 129 | if (interval != 0) | |
| 130 | 			{
 | |
| 131 | iFeedTimer.SetPeriod(interval); | |
| 132 | iFeedTimer.RunPeriodically(); | |
| 133 | } | |
| 134 | } | |
| 135 | } | |
| 136 | ||
| 137 | EXPORT_C void CFeedEngine::UpdateAllFeedsL(TBool aAutoUpdate) | |
| 138 | 	{
 | |
| 139 | iAutoUpdatedInitiator = aAutoUpdate; | |
| 140 | if (iFeedsUpdating.Count() > 0) | |
| 141 | 		{
 | |
| 142 | 		DP("Cancelling update");
 | |
| 143 | iFeedClient->Stop(); | |
| 144 | iFeedsUpdating.Reset(); | |
| 145 | return; | |
| 146 | } | |
| 147 | ||
| 148 | TInt cnt = iSortedFeeds.Count(); | |
| 149 | for (int i=0;i<cnt;i++) | |
| 150 | 		{
 | |
| 151 | iFeedsUpdating.Append(iSortedFeeds[i]); | |
| 152 | } | |
| 153 | ||
| 154 | UpdateNextFeedL(); | |
| 155 | } | |
| 156 | ||
| 157 | EXPORT_C void CFeedEngine::CancelUpdateAllFeeds() | |
| 158 | 	{
 | |
| 159 | if(iClientState != EIdle) | |
| 160 | 		{
 | |
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 161 | iCancelRequested = ETrue; | 
| 2 | 162 | iFeedsUpdating.Reset(); | 
| 163 | iFeedClient->Stop(); | |
| 164 | } | |
| 165 | } | |
| 166 | ||
| 167 | void CFeedEngine::UpdateNextFeedL() | |
| 168 | 	{
 | |
| 169 | 	DP1("UpdateNextFeed. %d feeds left to update", iFeedsUpdating.Count());
 | |
| 170 | ||
| 171 | if (iFeedsUpdating.Count() > 0) | |
| 172 | 		{
 | |
| 173 | CFeedInfo *info = iFeedsUpdating[0]; | |
| 174 | iFeedsUpdating.Remove(0); | |
| 175 | TBool result = EFalse; | |
| 176 | 		//DP2("** UpdateNextFeed: %S, ID: %u", &(info->Url()), info->Uid());
 | |
| 177 | TRAPD(error, result = UpdateFeedL(info->Uid())); | |
| 178 | ||
| 179 | if (error != KErrNone || !result) | |
| 180 | 			{
 | |
| 181 | 			DP("Error while updating all feeds");
 | |
| 182 | for (TInt i=0;i<iObservers.Count();i++) | |
| 183 | 				{
 | |
| 184 | TRAP_IGNORE(iObservers[i]->FeedUpdateAllCompleteL(iAutoUpdatedInitiator?MFeedEngineObserver::EFeedAutoUpdate:MFeedEngineObserver::EFeedManualUpdate)); | |
| 185 | } | |
| 186 | } | |
| 187 | } | |
| 188 | else | |
| 189 | 		{
 | |
| 190 | iClientState = EIdle; | |
| 191 | for (TInt i=0;i<iObservers.Count();i++) | |
| 192 | 			{
 | |
| 193 | TRAP_IGNORE(iObservers[i]->FeedUpdateAllCompleteL(iAutoUpdatedInitiator?MFeedEngineObserver::EFeedAutoUpdate:MFeedEngineObserver::EFeedManualUpdate)); | |
| 194 | } | |
| 195 | } | |
| 196 | } | |
| 197 | ||
| 198 | EXPORT_C TBool CFeedEngine::UpdateFeedL(TUint aFeedUid) | |
| 199 | 	{
 | |
| 200 | 	DP("FeedEngine::UpdateFeedL BEGIN");
 | |
| 201 | iActiveFeed = GetFeedInfoByUid(aFeedUid); | |
| 202 | iCatchupCounter = 0; | |
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 203 | iCancelRequested = EFalse; | 
| 2 | 204 | |
| 205 | if (iActiveFeed->LastUpdated() == 0) | |
| 206 | 		{
 | |
| 207 | iCatchupMode = ETrue; | |
| 208 | } | |
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 209 | |
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 210 | iActiveFeed->SetLastError(KErrNone); | 
| 36 
e010fc411ddc
Merge, plus minor fix to CFeedEngine
 Brendan Donegan <brendand@symbian.org>diff
changeset | 211 | DBUpdateFeedL(*iActiveFeed); | 
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 212 | |
| 2 | 213 | iUpdatingFeedFileName.Copy (iPodcastModel.SettingsEngine().PrivatePath ()); | 
| 214 | _LIT(KFileNameFormat, "%lu.xml"); | |
| 215 | iUpdatingFeedFileName.AppendFormat(KFileNameFormat, aFeedUid); | |
| 216 | ||
| 217 | if(iFeedClient->GetL(iActiveFeed->Url(), iUpdatingFeedFileName, iPodcastModel.SettingsEngine().SpecificIAP())) | |
| 218 | 		{
 | |
| 219 | iClientState = EUpdatingFeed; | |
| 220 | ||
| 221 | for (TInt i=0;i<iObservers.Count();i++) | |
| 222 | 			{
 | |
| 223 | TRAP_IGNORE(iObservers[i]->FeedDownloadStartedL(iAutoUpdatedInitiator?MFeedEngineObserver::EFeedAutoUpdate:MFeedEngineObserver::EFeedManualUpdate, iActiveFeed->Uid())); | |
| 224 | } | |
| 225 | ||
| 226 | 		DP("FeedEngine::UpdateFeedL END, return ETrue");
 | |
| 227 | return ETrue; | |
| 228 | } | |
| 229 | else | |
| 230 | 		{
 | |
| 231 | 		DP("FeedEngine::UpdateFeedL END, return EFalse");
 | |
| 232 | return EFalse; | |
| 233 | } | |
| 234 | } | |
| 235 | ||
| 236 | void CFeedEngine::NewShowL(CShowInfo& aItem) | |
| 237 | 	{
 | |
| 238 | HBufC* description = HBufC::NewLC(KMaxDescriptionLength); | |
| 239 | TPtr ptr(description->Des()); | |
| 240 | ptr.Copy(aItem.Description()); | |
| 241 | PodcastUtils::CleanHtmlL(ptr); | |
| 8 | 242 | |
| 243 | aItem.SetDescriptionL(*description); | |
| 2 | 244 | CleanupStack::PopAndDestroy(description); | 
| 245 | ||
| 246 | 	if (iCatchupMode) {
 | |
| 247 | // in catchup mode, we let one show be unplayed | |
| 248 | 		if (++iCatchupCounter > 1) {
 | |
| 249 | aItem.SetPlayState(EPlayed); | |
| 250 | } | |
| 251 | } | |
| 252 | ||
| 253 | TBool isShowAdded = iPodcastModel.ShowEngine().AddShowL(aItem); | |
| 254 | ||
| 255 | if (aItem.PlayState() == ENeverPlayed && isShowAdded && iPodcastModel.SettingsEngine().DownloadAutomatically()) | |
| 256 | 		{
 | |
| 257 | iPodcastModel.ShowEngine().AddDownloadL(aItem); | |
| 258 | } | |
| 259 | } | |
| 260 | ||
| 261 | void CFeedEngine::GetFeedImageL(CFeedInfo *aFeedInfo) | |
| 262 | 	{
 | |
| 263 | 	DP("GetFeedImage");
 | |
| 264 | ||
| 265 | TFileName filePath; | |
| 266 | filePath.Copy(iPodcastModel.SettingsEngine().BaseDir()); | |
| 267 | ||
| 268 | // create relative file name | |
| 269 | TFileName relPath; | |
| 270 | relPath.Copy(aFeedInfo->Title()); | |
| 271 | 	relPath.Append('\\');
 | |
| 272 | ||
| 273 | TFileName fileName; | |
| 274 | PodcastUtils::FileNameFromUrl(aFeedInfo->ImageUrl(), fileName); | |
| 275 | relPath.Append(fileName); | |
| 276 | PodcastUtils::EnsureProperPathName(relPath); | |
| 277 | ||
| 278 | // complete file path is base dir + rel path | |
| 279 | filePath.Append(relPath); | |
| 100 
e0fc52a5df4d
Update to keep features from merge.
 Lars Persson <lars.persson@embeddev.se> parents: 
99diff
changeset | 280 | aFeedInfo->SetImageFileNameL(filePath, NULL); | 
| 2 | 281 | |
| 282 | if(iFeedClient->GetL(aFeedInfo->ImageUrl(), filePath, ETrue)) | |
| 283 | 		{
 | |
| 284 | iClientState = EUpdatingImage; | |
| 285 | } | |
| 286 | } | |
| 287 | ||
| 288 | EXPORT_C TBool CFeedEngine::AddFeedL(const CFeedInfo&aItem) | |
| 289 | 	{
 | |
| 290 | 	DP2("CFeedEngine::AddFeed, title=%S, URL=%S", &aItem.Title(), &aItem.Url());
 | |
| 291 | for (TInt i=0;i<iSortedFeeds.Count();i++) | |
| 292 | 		{
 | |
| 293 | if (iSortedFeeds[i]->Uid() == aItem.Uid()) | |
| 294 | 			{
 | |
| 295 | 			DP1("Already have feed %S, discarding", &aItem.Url());			
 | |
| 296 | return EFalse; | |
| 297 | } | |
| 298 | } | |
| 299 | ||
| 300 | TLinearOrder<CFeedInfo> sortOrder( CFeedEngine::CompareFeedsByTitle); | |
| 301 | CFeedInfo* newItem = aItem.CopyL(); | |
| 302 | CleanupStack::PushL(newItem); | |
| 303 | User::LeaveIfError(iSortedFeeds.InsertInOrder(newItem, sortOrder)); | |
| 304 | CleanupStack::Pop(newItem); | |
| 305 | ||
| 306 | ||
| 307 | // Save the feeds into DB | |
| 308 | DBAddFeedL(aItem); | |
| 309 | return ETrue; | |
| 310 | } | |
| 311 | ||
| 312 | TBool CFeedEngine::DBAddFeedL(const CFeedInfo& aItem) | |
| 313 | 	{
 | |
| 314 | 	DP2("CFeedEngine::DBAddFeed, title=%S, URL=%S", &aItem.Title(), &aItem.Url());
 | |
| 315 | ||
| 316 | CFeedInfo *info = DBGetFeedInfoByUidL(aItem.Uid()); | |
| 317 | 	if (info) {
 | |
| 318 | 		DP("Feed already exists!");
 | |
| 319 | delete info; | |
| 320 | return EFalse; | |
| 321 | } | |
| 322 | ||
| 323 | HBufC* titleBuf = HBufC::NewLC(KMaxLineLength); | |
| 324 | TPtr titlePtr(titleBuf->Des()); | |
| 325 | titlePtr.Copy(aItem.Title()); | |
| 326 | PodcastUtils::SQLEncode(titlePtr); | |
| 327 | ||
| 328 | HBufC* descBuf = HBufC::NewLC(KMaxLineLength); | |
| 329 | TPtr descPtr(descBuf->Des()); | |
| 330 | descPtr.Copy(aItem.Description()); | |
| 331 | PodcastUtils::SQLEncode(descPtr); | |
| 332 | ||
| 333 | _LIT(KSqlStatement, "insert into feeds (url, title, description, imageurl, imagefile, link, built, lastupdated, uid, feedtype, customtitle, lasterror)" | |
| 334 | " values (\"%S\",\"%S\", \"%S\", \"%S\", \"%S\", \"%S\", \"%Ld\", \"%Ld\", \"%u\", \"%u\", \"%u\", \"%d\")"); | |
| 335 | iSqlBuffer.Format(KSqlStatement, | |
| 336 | &aItem.Url(), titleBuf, descBuf, &aItem.ImageUrl(), &aItem.ImageFileName(), &aItem.Link(), | |
| 337 | aItem.BuildDate().Int64(), aItem.LastUpdated().Int64(), aItem.Uid(), EAudioPodcast, aItem.CustomTitle(), aItem.LastError()); | |
| 338 | ||
| 339 | CleanupStack::PopAndDestroy(descBuf); | |
| 340 | CleanupStack::PopAndDestroy(titleBuf); | |
| 341 | ||
| 342 | sqlite3_stmt *st; | |
| 343 | ||
| 344 | 	//DP1("SQL statement length=%d", iSqlBuffer.Length());
 | |
| 345 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 346 | ||
| 347 | if (rc==SQLITE_OK) | |
| 348 | 		{
 | |
| 349 | rc = sqlite3_step(st); | |
| 350 | ||
| 351 | if (rc == SQLITE_DONE) | |
| 352 | 			{
 | |
| 353 | sqlite3_finalize(st); | |
| 354 | return ETrue; | |
| 355 | } | |
| 356 | 		else {
 | |
| 357 | sqlite3_finalize(st); | |
| 358 | } | |
| 359 | } | |
| 360 | ||
| 361 | return EFalse; | |
| 362 | } | |
| 363 | ||
| 364 | EXPORT_C void CFeedEngine::RemoveFeedL(TUint aUid) | |
| 365 | 	{
 | |
| 366 | for (int i=0;i<iSortedFeeds.Count();i++) | |
| 367 | 		{
 | |
| 368 | if (iSortedFeeds[i]->Uid() == aUid) | |
| 369 | 			{
 | |
| 370 | iPodcastModel.ShowEngine().DeleteAllShowsByFeedL(aUid); | |
| 53 | 371 | |
| 2 | 372 | CFeedInfo* feedToRemove = iSortedFeeds[i]; | 
| 373 | ||
| 374 | //delete the image file if it exists | |
| 375 | if ((feedToRemove->ImageFileName().Length() >0) | |
| 376 | && BaflUtils::FileExists(iPodcastModel.FsSession(), feedToRemove->ImageFileName())) | |
| 377 | 				{
 | |
| 378 | iPodcastModel.FsSession().Delete(feedToRemove->ImageFileName()); | |
| 379 | } | |
| 380 | ||
| 381 | //delete the folder. It has the same name as the title. | |
| 382 | TFileName filePath; | |
| 383 | filePath.Copy(iPodcastModel.SettingsEngine().BaseDir()); | |
| 384 | filePath.Append(feedToRemove->Title()); | |
| 385 | 			filePath.Append('\\');
 | |
| 386 | iPodcastModel.FsSession().RmDir(filePath); | |
| 387 | ||
| 388 | iSortedFeeds.Remove(i); | |
| 389 | delete feedToRemove; | |
| 390 | ||
| 391 | 			DP("Removed feed from array");
 | |
| 392 | ||
| 393 | // now remove it from DB | |
| 394 | DBRemoveFeed(aUid); | |
| 395 | ||
| 396 | return; | |
| 397 | } | |
| 398 | } | |
| 399 | } | |
| 400 | ||
| 401 | ||
| 402 | TBool CFeedEngine::DBRemoveFeed(TUint aUid) | |
| 403 | 	{
 | |
| 404 | 	DP("CFeedEngine::DBRemoveFeed");
 | |
| 405 | _LIT(KSqlStatement, "delete from feeds where uid=%u"); | |
| 406 | iSqlBuffer.Format(KSqlStatement, aUid); | |
| 407 | ||
| 408 | sqlite3_stmt *st; | |
| 409 | ||
| 410 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 411 | ||
| 412 | if (rc==SQLITE_OK) | |
| 413 | 		{
 | |
| 414 | rc = sqlite3_step(st); | |
| 415 | sqlite3_finalize(st); | |
| 416 | ||
| 417 | if (rc == SQLITE_DONE) | |
| 418 | 			{
 | |
| 419 | 			DP("Feed removed from DB");
 | |
| 420 | return ETrue; | |
| 421 | } | |
| 422 | else | |
| 423 | 			{
 | |
| 424 | 			DP("Error when removing feed from DB");
 | |
| 425 | } | |
| 426 | } | |
| 427 | return EFalse; | |
| 428 | } | |
| 429 | ||
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 430 | TBool CFeedEngine::DBUpdateFeedL(const CFeedInfo &aItem) | 
| 2 | 431 | 	{
 | 
| 432 | 	DP2("CFeedEngine::DBUpdateFeed, title=%S, URL=%S", &aItem.Title(), &aItem.Url());
 | |
| 433 | ||
| 434 | HBufC* titleBuf = HBufC::NewLC(KMaxLineLength); | |
| 435 | TPtr titlePtr(titleBuf->Des()); | |
| 436 | titlePtr.Copy(aItem.Title()); | |
| 437 | PodcastUtils::SQLEncode(titlePtr); | |
| 438 | ||
| 439 | HBufC* descBuf = HBufC::NewLC(KMaxLineLength); | |
| 440 | TPtr descPtr(descBuf->Des()); | |
| 441 | descPtr.Copy(aItem.Description()); | |
| 442 | PodcastUtils::SQLEncode(descPtr); | |
| 443 | ||
| 444 | _LIT(KSqlStatement, "update feeds set url=\"%S\", title=\"%S\", description=\"%S\", imageurl=\"%S\", imagefile=\"%S\"," \ | |
| 445 | "link=\"%S\", built=\"%Lu\", lastupdated=\"%Lu\", feedtype=\"%u\", customtitle=\"%u\", lasterror=\"%d\" where uid=\"%u\""); | |
| 446 | iSqlBuffer.Format(KSqlStatement, | |
| 447 | &aItem.Url(), titleBuf, descBuf, &aItem.ImageUrl(), &aItem.ImageFileName(), &aItem.Link(), | |
| 448 | aItem.BuildDate().Int64(), aItem.LastUpdated().Int64(), EAudioPodcast, aItem.CustomTitle(), aItem.LastError(), aItem.Uid()); | |
| 449 | ||
| 450 | CleanupStack::PopAndDestroy(descBuf); | |
| 451 | CleanupStack::PopAndDestroy(titleBuf); | |
| 452 | ||
| 453 | sqlite3_stmt *st; | |
| 454 | ||
| 455 | 	//DP1("SQL statement length=%d", iSqlBuffer.Length());
 | |
| 456 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 457 | ||
| 458 | if (rc==SQLITE_OK) | |
| 459 | 		{
 | |
| 460 | rc = sqlite3_step(st); | |
| 461 | sqlite3_finalize(st); | |
| 462 | ||
| 463 | if (rc == SQLITE_DONE) | |
| 464 | 			{
 | |
| 465 | return ETrue; | |
| 466 | } | |
| 467 | } | |
| 468 | else | |
| 469 | 		{
 | |
| 470 | 		DP1("SQLite rc=%d", rc);
 | |
| 471 | } | |
| 472 | ||
| 473 | return EFalse; | |
| 474 | } | |
| 475 | ||
| 476 | void CFeedEngine::ParsingCompleteL(CFeedInfo *item) | |
| 477 | 	{
 | |
| 478 | TBuf<KMaxLineLength> title; | |
| 479 | title.Copy(item->Title()); | |
| 8 | 480 | item->SetTitleL(title); // if this leaves we are out of memory | 
| 2 | 481 | } | 
| 482 | ||
| 483 | ||
| 484 | EXPORT_C void CFeedEngine::AddObserver(MFeedEngineObserver *observer) | |
| 485 | 	{
 | |
| 486 | iObservers.Append(observer); | |
| 487 | } | |
| 488 | ||
| 489 | EXPORT_C void CFeedEngine::RemoveObserver(MFeedEngineObserver *observer) | |
| 490 | 	{
 | |
| 491 | TInt index = iObservers.Find(observer); | |
| 492 | ||
| 493 | if (index > KErrNotFound) | |
| 494 | 		{
 | |
| 495 | iObservers.Remove(index); | |
| 496 | } | |
| 497 | } | |
| 498 | ||
| 499 | void CFeedEngine::Connected(CHttpClient* /*aClient*/) | |
| 500 | 	{
 | |
| 501 | } | |
| 502 | ||
| 503 | void CFeedEngine::Progress(CHttpClient* /*aHttpClient*/, TInt /*aBytes*/, TInt /*aTotalBytes*/) | |
| 504 | 	{	
 | |
| 505 | } | |
| 506 | ||
| 507 | void CFeedEngine::CompleteL(CHttpClient* /*aClient*/, TInt aError) | |
| 508 | 	{
 | |
| 509 | 	DP2("CFeedEngine::CompleteL BEGIN, iClientState=%d, aSuccessful=%d", iClientState, aError);
 | |
| 510 | ||
| 511 | switch(iClientState) | |
| 512 | 		{		
 | |
| 513 | default: | |
| 514 | if(iActiveFeed != NULL) | |
| 515 | 				{
 | |
| 516 | TTime time; | |
| 517 | time.HomeTime(); | |
| 518 | iActiveFeed->SetLastUpdated(time); | |
| 519 | iActiveFeed->SetLastError(aError); | |
| 96 | 520 | NotifyFeedUpdateComplete(iActiveFeed->Uid(), aError); | 
| 2 | 521 | } | 
| 522 | break; | |
| 523 | case EUpdatingFeed: | |
| 524 | 		{
 | |
| 525 | // Parse the feed. We need to trap this call since it could leave and then | |
| 526 | // the whole update chain will be broken | |
| 527 | // change client state | |
| 528 | iClientState = EIdle; | |
| 529 | switch (aError) | |
| 530 | 			{
 | |
| 531 | case KErrCancel: | |
| 532 | 				{
 | |
| 533 | iFeedsUpdating.Reset(); | |
| 534 | } | |
| 535 | break; | |
| 536 | case KErrCouldNotConnect: | |
| 537 | iFeedsUpdating.Reset(); | |
| 538 | break; | |
| 539 | default: | |
| 540 | 				{
 | |
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 541 | 				if (!iCancelRequested) {
 | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 542 | iActiveFeed->SetLastError(aError); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 543 | TTime time; | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 544 | time.HomeTime(); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 545 | iActiveFeed->SetLastUpdated(time); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 546 | |
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 547 | if( aError == KErrNone) | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 548 | 						{			
 | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 549 | TRAPD(parserErr, iParser->ParseFeedL(iUpdatingFeedFileName, iActiveFeed, iPodcastModel.SettingsEngine().MaxListItems())); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 550 | |
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 551 | if(parserErr) | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 552 | 							{
 | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 553 | // we do not need to any special action on this error. | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 554 | iActiveFeed->SetLastError(parserErr); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 555 | 							DP1("CFeedEngine::Complete()\t Failed to parse feed. Leave with error code=%d", parserErr);
 | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 556 | } | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 557 | else | 
| 2 | 558 | 							{
 | 
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 559 | iPodcastModel.ShowEngine().DeleteOldShowsByFeed(iActiveFeed->Uid()); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 560 | } | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 561 | |
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 562 | // delete the downloaded XML file as it is no longer needed | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 563 | BaflUtils::DeleteFile(iPodcastModel.FsSession(),iUpdatingFeedFileName); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 564 | |
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 565 | // if the feed has specified a image url. download it if we dont already have it | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 566 | if((iActiveFeed->ImageUrl().Length() > 0)) | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 567 | 							{
 | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 568 | if ( (iActiveFeed->ImageFileName().Length() == 0) || | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 569 | (iActiveFeed->ImageFileName().Length() > 0 && | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 570 | !BaflUtils::FileExists(iPodcastModel.FsSession(), | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 571 | iActiveFeed->ImageFileName()) ) | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 572 | ) | 
| 2 | 573 | 								{
 | 
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 574 | TRAPD(error, GetFeedImageL(iActiveFeed)); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 575 | if (error) | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 576 | 									{
 | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 577 | // we have failed in a very early stage to fetch the image. | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 578 | // continue with next Feed update | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 579 | iActiveFeed->SetLastError(parserErr); | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 580 | iClientState = EIdle; | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 581 | } | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 582 | } | 
| 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 583 | } | 
| 2 | 584 | } | 
| 585 | } | |
| 32 
26a3f2dfba08
Fix for bug where we always load the feed icon a large number of times
 teknolog parents: 
8diff
changeset | 586 | iCancelRequested = EFalse; | 
| 2 | 587 | }break; | 
| 588 | } | |
| 589 | ||
| 96 | 590 | NotifyFeedUpdateComplete(iActiveFeed->Uid(), aError); | 
| 591 | ||
| 7 | 592 | // we will wait until the image has been downloaded to start the next feed update. | 
| 593 | if (iClientState == EIdle) | |
| 594 | 				{
 | |
| 595 | UpdateNextFeedL(); | |
| 596 | } | |
| 597 | }break; | |
| 598 | case EUpdatingImage: | |
| 599 | 			{
 | |
| 600 | // change client state to not updating | |
| 601 | iClientState = EIdle; | |
| 91 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 602 | if(aError == KErrNone) | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 603 | 				{
 | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 604 | if( BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), iActiveFeed->ImageFileName() )) | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 605 | 					{
 | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 606 | // If this fails, no reason to worry | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 607 | TRAP_IGNORE(iPodcastModel.ImageHandler().LoadFileAndScaleL(iActiveFeed->FeedIcon(), iActiveFeed->ImageFileName(), TSize(64,56), *iActiveFeed, iActiveFeed->Uid())); | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 608 | } | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 609 | } | 
| 
87cb33beeae2
Remove icon index. Start caching icons as mbms.
 Lars Persson <lars.persson@embeddev.se> parents: 
32diff
changeset | 610 | |
| 96 | 611 | NotifyFeedUpdateComplete(iActiveFeed->Uid(), aError); | 
| 7 | 612 | UpdateNextFeedL(); | 
| 613 | }break; | |
| 614 | case ESearching: | |
| 2 | 615 | 			{
 | 
| 7 | 616 | iClientState = EIdle; | 
| 617 | ||
| 618 | 			DP2("Search complete, results in %S with error %d", &iSearchResultsFileName, aError);
 | |
| 619 | if(aError == KErrNone) | |
| 2 | 620 | 				{
 | 
| 7 | 621 | if (!iOpmlParser) | 
| 622 | 					{
 | |
| 623 | iOpmlParser = new COpmlParser(*this, iPodcastModel.FsSession()); | |
| 624 | } | |
| 625 | ||
| 626 | 				DP("Parsing OPML");
 | |
| 627 | iOpmlParser->ParseOpmlL(iSearchResultsFileName, ETrue); | |
| 2 | 628 | } | 
| 7 | 629 | else | 
| 630 | 				{
 | |
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 631 | NotifyOpmlParsingCompleteL(aError, 0); | 
| 7 | 632 | } | 
| 633 | ||
| 634 | BaflUtils::DeleteFile(iPodcastModel.FsSession(), iSearchResultsFileName); | |
| 635 | }break; | |
| 2 | 636 | } | 
| 637 | 	DP("CFeedEngine::CompleteL END");
 | |
| 638 | } | |
| 639 | ||
| 93 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 640 | void CFeedEngine::NotifyFeedUpdateComplete(TInt aFeedUid, TInt aError) | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 641 | 	{
 | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 642 | 	DP("CFeedEngine::NotifyFeedUpdateComplete");	
 | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 643 | for (TInt i=0;i<iObservers.Count();i++) | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 644 | 		{
 | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 645 | TRAP_IGNORE(iObservers[i]->FeedDownloadFinishedL(MFeedEngineObserver::EFeedAutoUpdate, aFeedUid, aError)); | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 646 | } | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 647 | } | 
| 
bbf5c5204844
We always build the static version of sqlite for now. Further improvements for signaling when icons has been generated so these can be used in the feedview
 Lars Persson <lars.persson@embeddev.se> parents: 
91diff
changeset | 648 | |
| 2 | 649 | void CFeedEngine::Disconnected(CHttpClient* /*aClient*/) | 
| 650 | 	{
 | |
| 651 | } | |
| 652 | ||
| 653 | void CFeedEngine::DownloadInfo(CHttpClient* /*aHttpClient */, int /*aTotalBytes*/) | |
| 654 | 	{	
 | |
| 655 | 	/*DP1("About to download %d bytes", aTotalBytes);
 | |
| 656 | 	if(aHttpClient == iShowClient && iShowDownloading != NULL && aTotalBytes != -1) {
 | |
| 657 | iShowDownloading->iShowSize = aTotalBytes; | |
| 658 | }*/ | |
| 659 | } | |
| 660 | ||
| 661 | EXPORT_C void CFeedEngine::ImportFeedsL(const TDesC& aFile) | |
| 662 | 	{
 | |
| 663 | TFileName opmlPath; | |
| 664 | opmlPath.Copy(aFile); | |
| 665 | ||
| 666 | 	if (!iOpmlParser) {
 | |
| 667 | iOpmlParser = new COpmlParser(*this, iPodcastModel.FsSession()); | |
| 668 | } | |
| 669 | ||
| 670 | iOpmlParser->ParseOpmlL(opmlPath, EFalse); | |
| 671 | } | |
| 672 | ||
| 673 | EXPORT_C TBool CFeedEngine::ExportFeedsL(TFileName& aFile) | |
| 674 | 	{
 | |
| 675 | RFile rfile; | |
| 676 | TFileName privatePath; | |
| 677 | iPodcastModel.FsSession().PrivatePath(privatePath); | |
| 678 | TInt error = rfile.Temp(iPodcastModel.FsSession(), privatePath, aFile, EFileWrite); | |
| 679 | if (error != KErrNone) | |
| 680 | 		{
 | |
| 681 | 		DP("CFeedEngine::ExportFeedsL()\tFailed to open file");
 | |
| 682 | return EFalse; | |
| 683 | } | |
| 684 | CleanupClosePushL(rfile); | |
| 685 | ||
| 686 | HBufC* templ = HBufC::NewLC(KMaxLineLength); | |
| 687 | templ->Des().Copy(KOpmlFeed()); | |
| 688 | ||
| 689 | HBufC* line = HBufC::NewLC(KMaxLineLength); | |
| 690 | HBufC* xmlUrl = HBufC::NewLC(KMaxURLLength); | |
| 691 | HBufC* htmlUrl = HBufC::NewLC(KMaxURLLength); | |
| 692 | HBufC* desc = HBufC::NewLC(KMaxDescriptionLength); | |
| 693 | HBufC* title = HBufC::NewLC(KMaxTitleLength); | |
| 694 | ||
| 695 | HBufC8* utf8line = CnvUtfConverter::ConvertFromUnicodeToUtf8L(KOpmlHeader()); | |
| 696 | ||
| 697 | rfile.Write(*utf8line); | |
| 698 | delete utf8line; | |
| 699 | ||
| 700 | for (int i=0; i<iSortedFeeds.Count(); i++) | |
| 701 | 		{
 | |
| 702 | CFeedInfo *info = iSortedFeeds[i]; | |
| 703 | 		DP1("Exporting feed '%S'", &iSortedFeeds[i]->Title());
 | |
| 704 | ||
| 705 | // XML URL | |
| 706 | TPtr ptrXml(xmlUrl->Des()); | |
| 707 | if (info->Url() != KNullDesC) | |
| 708 | 			{
 | |
| 709 | ptrXml.Copy(info->Url()); | |
| 710 | PodcastUtils::XMLEncode(ptrXml); | |
| 711 | } | |
| 712 | ||
| 713 | // Description | |
| 714 | TPtr ptrDesc(desc->Des()); | |
| 715 | ptrDesc.Zero(); | |
| 716 | 		if (info->Description() != KNullDesC) {
 | |
| 717 | ptrDesc.Copy(info->Description()); | |
| 718 | PodcastUtils::XMLEncode(ptrDesc); | |
| 719 | } | |
| 720 | ||
| 721 | // Title | |
| 722 | TPtr ptrTitle(title->Des()); | |
| 723 | ptrTitle.Zero(); | |
| 724 | ||
| 725 | 		if (info->Title() != KNullDesC) {
 | |
| 726 | ptrTitle.Copy(info->Title()); | |
| 727 | PodcastUtils::XMLEncode(ptrTitle); | |
| 728 | } | |
| 729 | ||
| 730 | // HTML URL | |
| 731 | TPtr ptrHtmlUrl(htmlUrl->Des()); | |
| 732 | ptrHtmlUrl.Zero(); | |
| 733 | ||
| 734 | 		if (info->Link() != KNullDesC) {
 | |
| 735 | ptrHtmlUrl.Copy(info->Link()); | |
| 736 | PodcastUtils::XMLEncode(ptrHtmlUrl); | |
| 737 | } | |
| 738 | // Write line to OPML file | |
| 739 | line->Des().Format(*templ, title, desc, xmlUrl, htmlUrl); | |
| 740 | utf8line = CnvUtfConverter::ConvertFromUnicodeToUtf8L(*line); | |
| 741 | rfile.Write(*utf8line); | |
| 742 | delete utf8line; | |
| 743 | } | |
| 744 | ||
| 745 | utf8line = CnvUtfConverter::ConvertFromUnicodeToUtf8L(KOpmlFooter()); | |
| 746 | rfile.Write(*utf8line); | |
| 747 | delete utf8line; | |
| 748 | ||
| 749 | CleanupStack::PopAndDestroy(7);//destroy 6 bufs & close rfile | |
| 750 | ||
| 751 | return ETrue; | |
| 752 | } | |
| 753 | ||
| 754 | EXPORT_C CFeedInfo* CFeedEngine::GetFeedInfoByUid(TUint aFeedUid) | |
| 755 | 	{
 | |
| 756 | TInt cnt = iSortedFeeds.Count(); | |
| 757 | for (TInt i=0;i<cnt;i++) | |
| 758 | 		{
 | |
| 759 | if (iSortedFeeds[i]->Uid() == aFeedUid) | |
| 760 | 			{
 | |
| 761 | return iSortedFeeds[i]; | |
| 762 | } | |
| 763 | } | |
| 764 | ||
| 765 | return NULL; | |
| 766 | } | |
| 767 | ||
| 768 | EXPORT_C const RFeedInfoArray& CFeedEngine::GetSortedFeeds() | |
| 769 | {
 | |
| 770 | TLinearOrder<CFeedInfo> sortOrder( CFeedEngine::CompareFeedsByTitle); | |
| 771 | ||
| 772 | iSortedFeeds.Sort(sortOrder); | |
| 773 | return iSortedFeeds; | |
| 774 | } | |
| 775 | ||
| 776 | TInt CFeedEngine::CompareFeedsByTitle(const CFeedInfo &a, const CFeedInfo &b) | |
| 777 | 	{
 | |
| 778 | 		//DP2("Comparing %S to %S", &a.Title(), &b.Title());
 | |
| 779 | return a.Title().CompareF(b.Title()); | |
| 780 | } | |
| 781 | ||
| 782 | EXPORT_C void CFeedEngine::GetDownloadedStats(TUint &aNumShows, TUint &aNumUnplayed) | |
| 783 | 	{
 | |
| 784 | 	DP("CFeedEngine::GetDownloadedStats");
 | |
| 785 | _LIT(KSqlStatement, "select count(*) from shows where downloadstate=%u"); | |
| 786 | iSqlBuffer.Format(KSqlStatement, EDownloaded); | |
| 787 | ||
| 788 | sqlite3_stmt *st; | |
| 789 | ||
| 790 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 791 | ||
| 792 | 	if( rc==SQLITE_OK ){
 | |
| 793 | rc = sqlite3_step(st); | |
| 794 | ||
| 795 | 	  	if (rc == SQLITE_ROW) {
 | |
| 796 | aNumShows = sqlite3_column_int(st, 0); | |
| 797 | } | |
| 798 | } | |
| 799 | ||
| 800 | sqlite3_finalize(st); | |
| 801 | ||
| 802 | _LIT(KSqlStatement2, "select count(*) from shows where downloadstate=%u and playstate=%u"); | |
| 803 | iSqlBuffer.Format(KSqlStatement2, EDownloaded, ENeverPlayed); | |
| 804 | ||
| 805 | rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 806 | ||
| 807 | 	if( rc==SQLITE_OK ){
 | |
| 808 | rc = sqlite3_step(st); | |
| 809 | ||
| 810 | 	  	if (rc == SQLITE_ROW) {
 | |
| 811 | aNumUnplayed = sqlite3_column_int(st, 0); | |
| 812 | } | |
| 813 | } | |
| 814 | ||
| 815 | sqlite3_finalize(st); | |
| 816 | } | |
| 817 | ||
| 818 | EXPORT_C void CFeedEngine::GetStatsByFeed(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed) | |
| 819 | 	{
 | |
| 820 | 	//DP1("CFeedEngine::GetStatsByFeed, aFeedUid=%u", aFeedUid);
 | |
| 821 | DBGetStatsByFeed(aFeedUid, aNumShows, aNumUnplayed); | |
| 822 | } | |
| 823 | ||
| 824 | void CFeedEngine::DBGetStatsByFeed(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed) | |
| 825 | 	{
 | |
| 826 | 	//DP1("CFeedEngine::DBGetStatsByFeed, feedUid=%u", aFeedUid);
 | |
| 827 | _LIT(KSqlStatement, "select count(*) from shows where feeduid=%u"); | |
| 828 | iSqlBuffer.Format(KSqlStatement, aFeedUid); | |
| 829 | ||
| 830 | sqlite3_stmt *st; | |
| 831 | ||
| 832 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 833 | ||
| 834 | 	if( rc==SQLITE_OK ){
 | |
| 835 | rc = sqlite3_step(st); | |
| 836 | ||
| 837 | 	  	if (rc == SQLITE_ROW) {
 | |
| 838 | aNumShows = sqlite3_column_int(st, 0); | |
| 839 | } | |
| 840 | } | |
| 841 | ||
| 842 | sqlite3_finalize(st); | |
| 843 | ||
| 844 | _LIT(KSqlStatement2, "select count(*) from shows where feeduid=%u and playstate=0"); | |
| 845 | iSqlBuffer.Format(KSqlStatement2, aFeedUid); | |
| 846 | ||
| 847 | rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 848 | ||
| 849 | 	if( rc==SQLITE_OK ){
 | |
| 850 | rc = sqlite3_step(st); | |
| 851 | ||
| 852 | 	  	if (rc == SQLITE_ROW) {
 | |
| 853 | aNumUnplayed = sqlite3_column_int(st, 0); | |
| 854 | } | |
| 855 | } | |
| 856 | ||
| 857 | sqlite3_finalize(st); | |
| 858 | } | |
| 859 | ||
| 860 | TUint CFeedEngine::DBGetFeedCount() | |
| 861 | 	{
 | |
| 862 | 	 DP("DBGetFeedCount BEGIN");
 | |
| 863 | sqlite3_stmt *st; | |
| 864 | int rc = sqlite3_prepare_v2(&iDB,"select count(*) from feeds" , -1, &st, (const char**) NULL); | |
| 865 | TUint size = 0; | |
| 866 | ||
| 867 | 	 if( rc==SQLITE_OK ){
 | |
| 868 | rc = sqlite3_step(st); | |
| 869 | ||
| 870 | 	  	if (rc == SQLITE_ROW) {
 | |
| 871 | size = sqlite3_column_int(st, 0); | |
| 872 | } | |
| 873 | } | |
| 874 | ||
| 875 | sqlite3_finalize(st); | |
| 876 | 	  DP1("DBGetFeedCount END=%d", size);
 | |
| 877 | return size; | |
| 878 | } | |
| 879 | ||
| 880 | void CFeedEngine::DBLoadFeedsL() | |
| 881 | 	{
 | |
| 882 | 	DP("DBLoadFeeds BEGIN");
 | |
| 883 | iSortedFeeds.Reset(); | |
| 884 | CFeedInfo *feedInfo = NULL; | |
| 885 | ||
| 886 | _LIT(KSqlStatement, "select url, title, description, imageurl, imagefile, link, built, lastupdated, uid, feedtype, customtitle from feeds"); | |
| 887 | iSqlBuffer.Format(KSqlStatement); | |
| 888 | ||
| 889 | sqlite3_stmt *st; | |
| 890 | ||
| 891 | TLinearOrder<CFeedInfo> sortOrder( CFeedEngine::CompareFeedsByTitle); | |
| 892 | ||
| 893 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 894 | Cleanup_sqlite3_finalize_PushL(st); | |
| 895 | ||
| 896 | 	if (rc==SQLITE_OK) {
 | |
| 897 | rc = sqlite3_step(st); | |
| 898 | 		while(rc == SQLITE_ROW) {
 | |
| 899 | feedInfo = CFeedInfo::NewLC(); | |
| 900 | ||
| 901 | const void *urlz = sqlite3_column_text16(st, 0); | |
| 902 | TPtrC16 url((const TUint16*)urlz); | |
| 903 | feedInfo->SetUrlL(url); | |
| 904 | ||
| 905 | const void *titlez = sqlite3_column_text16(st, 1); | |
| 906 | TPtrC16 title((const TUint16*)titlez); | |
| 907 | feedInfo->SetTitleL(title); | |
| 908 | ||
| 909 | const void *descz = sqlite3_column_text16(st, 2); | |
| 910 | TPtrC16 desc((const TUint16*)descz); | |
| 911 | feedInfo->SetDescriptionL(desc); | |
| 912 | ||
| 913 | const void *imagez = sqlite3_column_text16(st, 3); | |
| 914 | TPtrC16 image((const TUint16*)imagez); | |
| 915 | feedInfo->SetImageUrlL(image); | |
| 916 | ||
| 917 | const void *imagefilez = sqlite3_column_text16(st, 4); | |
| 918 | TPtrC16 imagefile((const TUint16*)imagefilez); | |
| 100 
e0fc52a5df4d
Update to keep features from merge.
 Lars Persson <lars.persson@embeddev.se> parents: 
99diff
changeset | 919 | feedInfo->SetImageFileNameL(imagefile, &iPodcastModel); | 
| 2 | 920 | |
| 921 | const void *linkz = sqlite3_column_text16(st, 5); | |
| 922 | TPtrC16 link((const TUint16*)linkz); | |
| 923 | feedInfo->SetDescriptionL(link); | |
| 924 | ||
| 925 | sqlite3_int64 built = sqlite3_column_int64(st, 6); | |
| 926 | TTime buildtime(built); | |
| 927 | feedInfo->SetBuildDate(buildtime); | |
| 928 | ||
| 929 | sqlite3_int64 lastupdated = sqlite3_column_int64(st, 7); | |
| 930 | TTime lastupdatedtime(lastupdated); | |
| 931 | feedInfo->SetLastUpdated(lastupdatedtime); | |
| 932 | ||
| 933 | sqlite3_int64 customtitle = sqlite3_column_int64(st, 10); | |
| 934 | 			if (customtitle) {
 | |
| 935 | feedInfo->SetCustomTitle(); | |
| 936 | } | |
| 937 | ||
| 938 | TInt lasterror = sqlite3_column_int(st, 11); | |
| 939 | feedInfo->SetLastError(lasterror); | |
| 940 | ||
| 941 | TLinearOrder<CFeedInfo> sortOrder( CFeedEngine::CompareFeedsByTitle); | |
| 942 | ||
| 943 | iSortedFeeds.InsertInOrder(feedInfo, sortOrder); | |
| 944 | ||
| 945 | CleanupStack::Pop(feedInfo); | |
| 946 | ||
| 947 | rc = sqlite3_step(st); | |
| 948 | } | |
| 949 | } | |
| 950 | ||
| 951 | CleanupStack::PopAndDestroy();//st | |
| 952 | ||
| 953 | 	DP("DBLoadFeeds END");
 | |
| 954 | } | |
| 955 | ||
| 956 | CFeedInfo* CFeedEngine::DBGetFeedInfoByUidL(TUint aFeedUid) | |
| 957 | 	{
 | |
| 958 | 	DP("CFeedEngine::DBGetFeedInfoByUid");
 | |
| 959 | CFeedInfo *feedInfo = NULL; | |
| 960 | _LIT(KSqlStatement, "select url, title, description, imageurl, imagefile, link, built, lastupdated, uid, feedtype, customtitle, lasterror from feeds where uid=%u"); | |
| 961 | iSqlBuffer.Format(KSqlStatement, aFeedUid); | |
| 962 | ||
| 963 | sqlite3_stmt *st; | |
| 964 | ||
| 965 | 	//DP1("SQL statement length=%d", iSqlBuffer.Length());
 | |
| 966 | ||
| 967 | int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); | |
| 968 | ||
| 969 | 	if (rc==SQLITE_OK) {
 | |
| 970 | Cleanup_sqlite3_finalize_PushL(st); | |
| 971 | rc = sqlite3_step(st); | |
| 972 | 		if (rc == SQLITE_ROW) {
 | |
| 973 | feedInfo = CFeedInfo::NewLC(); | |
| 974 | ||
| 975 | const void *urlz = sqlite3_column_text16(st, 0); | |
| 976 | TPtrC16 url((const TUint16*)urlz); | |
| 977 | feedInfo->SetUrlL(url); | |
| 978 | ||
| 979 | const void *titlez = sqlite3_column_text16(st, 1); | |
| 980 | TPtrC16 title((const TUint16*)titlez); | |
| 981 | feedInfo->SetTitleL(title); | |
| 982 | ||
| 983 | const void *descz = sqlite3_column_text16(st, 2); | |
| 984 | TPtrC16 desc((const TUint16*)descz); | |
| 985 | feedInfo->SetDescriptionL(desc); | |
| 986 | ||
| 987 | const void *imagez = sqlite3_column_text16(st, 3); | |
| 988 | TPtrC16 image((const TUint16*)imagez); | |
| 989 | feedInfo->SetImageUrlL(image); | |
| 990 | ||
| 991 | const void *imagefilez = sqlite3_column_text16(st, 4); | |
| 992 | TPtrC16 imagefile((const TUint16*)imagefilez); | |
| 993 | feedInfo->SetDescriptionL(imagefile); | |
| 994 | ||
| 995 | const void *linkz = sqlite3_column_text16(st, 5); | |
| 996 | TPtrC16 link((const TUint16*)linkz); | |
| 997 | feedInfo->SetDescriptionL(link); | |
| 998 | ||
| 999 | sqlite3_int64 built = sqlite3_column_int64(st, 6); | |
| 1000 | TTime buildtime(built); | |
| 1001 | feedInfo->SetBuildDate(buildtime); | |
| 1002 | ||
| 1003 | sqlite3_int64 lastupdated = sqlite3_column_int64(st, 7); | |
| 1004 | TTime lastupdatedtime(lastupdated); | |
| 1005 | feedInfo->SetLastUpdated(lastupdatedtime); | |
| 1006 | ||
| 1007 | sqlite3_int64 customtitle = sqlite3_column_int64(st, 10); | |
| 1008 | 			if (customtitle) {
 | |
| 1009 | feedInfo->SetCustomTitle(); | |
| 1010 | } | |
| 1011 | ||
| 1012 | TInt lasterror = sqlite3_column_int(st, 11); | |
| 1013 | feedInfo->SetLastError(lasterror); | |
| 1014 | ||
| 1015 | CleanupStack::Pop(feedInfo); | |
| 1016 | } | |
| 1017 | CleanupStack::PopAndDestroy();//st | |
| 1018 | } | |
| 1019 | ||
| 1020 | return feedInfo; | |
| 1021 | } | |
| 1022 | ||
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 1023 | EXPORT_C void CFeedEngine::UpdateFeedL(CFeedInfo *aItem) | 
| 2 | 1024 | 	{
 | 
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 1025 | DBUpdateFeedL(*aItem); | 
| 2 | 1026 | } | 
| 1027 | ||
| 1028 | EXPORT_C void CFeedEngine::SearchForFeedL(TDesC& aSearchString) | |
| 1029 | 	{
 | |
| 1030 | 	DP1("FeedEngine::SearchForFeedL BEGIN, aSearchString=%S", &aSearchString);
 | |
| 1031 | ||
| 1032 | 	if (iClientState != EIdle) {
 | |
| 1033 | User::Leave(KErrInUse); | |
| 1034 | } | |
| 1035 | TBuf<KMaxURLLength> ssBuf; | |
| 1036 | ssBuf.Copy(aSearchString); | |
| 1037 | 	PodcastUtils::ReplaceString(ssBuf, _L(" "), _L("%20"));
 | |
| 1038 | // prepare search URL | |
| 1039 | HBufC* templ = HBufC::NewLC(KMaxLineLength); | |
| 1040 | templ->Des().Copy(KSearchUrl()); | |
| 1041 | ||
| 1042 | HBufC* url = HBufC::NewLC(KMaxURLLength); | |
| 1043 | url->Des().Format(*templ, &ssBuf); | |
| 1044 | ||
| 1045 | 	DP1("SearchURL: %S", url);
 | |
| 1046 | ||
| 1047 | // crate path to store OPML search results | |
| 1048 | iPodcastModel.FsSession().PrivatePath(iSearchResultsFileName); | |
| 1049 | ||
| 1050 | iSearchResultsFileName.Append(KSearchResultsFileName); | |
| 1051 | iSearchResults.ResetAndDestroy(); | |
| 1052 | // run search | |
| 1053 | if(iFeedClient->GetL(*url, iSearchResultsFileName, iPodcastModel.SettingsEngine().SpecificIAP())) | |
| 1054 | 		{
 | |
| 1055 | iClientState = ESearching; | |
| 1056 | } | |
| 1057 | else | |
| 1058 | 		{
 | |
| 1059 | iClientState = EIdle; | |
| 1060 | User::Leave(KErrAbort); | |
| 1061 | } | |
| 1062 | ||
| 1063 | CleanupStack::PopAndDestroy(url); | |
| 1064 | CleanupStack::PopAndDestroy(templ); | |
| 1065 | ||
| 1066 | 	DP("FeedEngine::SearchForFeedL END");
 | |
| 1067 | } | |
| 1068 | ||
| 1069 | EXPORT_C void CFeedEngine::AddSearchResultL(CFeedInfo *item) | |
| 1070 | 	{
 | |
| 1071 | 	DP1("CFeedEngine::AddSearchResultL, item->Title()=%S", &(item->Title()));
 | |
| 1072 | iSearchResults.AppendL(item); | |
| 1073 | } | |
| 1074 | ||
| 1075 | EXPORT_C const RFeedInfoArray& CFeedEngine::GetSearchResults() | |
| 1076 | 	{
 | |
| 1077 | return iSearchResults; | |
| 1078 | } | |
| 1079 | ||
| 1080 | ||
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 1081 | EXPORT_C void CFeedEngine::OpmlParsingCompleteL(TInt aError, TUint aNumFeedsAdded) | 
| 2 | 1082 | 	{
 | 
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 1083 | NotifyOpmlParsingCompleteL(aError, aNumFeedsAdded); | 
| 2 | 1084 | } | 
| 1085 | ||
| 35 
66c5303f3610
A ton of CodeScanner fixes (high issues) - but not all
 Brendan Donegan <brendand@symbian.org> parents: 
8diff
changeset | 1086 | void CFeedEngine::NotifyOpmlParsingCompleteL(TInt aError, TUint aNumFeedsAdded) | 
| 2 | 1087 | 	{
 | 
| 1088 | for (TInt i=0;i<iObservers.Count();i++) | |
| 1089 | 		{
 | |
| 7 | 1090 | iObservers[i]->OpmlParsingComplete(aError, aNumFeedsAdded); | 
| 2 | 1091 | } | 
| 1092 | } |