Error PMP300::WritePlaylist(DeviceInfo* device, vector<PlaylistItem*>* list, PLMCallBackFunction function, void* cookie) { Error result = kError_InvalidParam; assert(device); assert(list); if(device && list) { result = kError_DeviceNotFound; if(!strcasecmp(device->GetDevice(), devices[0].device)) { CRio rioInternal, rioExternal; bool rioPresent = false; rioPresent = FindRio(rioInternal, device, function, cookie); if(rioPresent) { FindRio(rioExternal, device, function, cookie); rioExternal.UseExternalFlash(true); if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString += "A "; event.eventString = device->GetDevice(); event.eventString += " has been found. Scanning internal memory..."; function(&event, cookie); } vector<PlaylistItem*> origInternal; vector<PlaylistItem*> origExternal; vector<PlaylistItem*> newInternal; vector<PlaylistItem*> newExternal; uint32 externalTotal = 0, internalTotal = 0, usedMem; uint32 count, index; char* path = new char[_MAX_PATH]; char* tempPath = new char[_MAX_PATH]; uint32 length = _MAX_PATH; // get a temp path m_context->prefs->GetPrefString(kInstallDirPref, tempPath, &length); strcat(tempPath, tmpnam(NULL)); #ifdef WIN32 mkdir(tempPath); #else mkdir(tempPath, S_IRWXU); #endif // first get current state of device // we break our lists into internal and // external lists for ease of organizing result = privateReadPlaylist(rioInternal, false, &internalTotal, &usedMem, &origInternal, function, cookie); if(IsntError(result)) { if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString = "Scanning external memory..."; function(&event, cookie); } privateReadPlaylist(rioExternal, true, &externalTotal, &usedMem, &origExternal, function, cookie); } count = list->size(); bool useExternal = false; for(index = 0; index < count; index++) { PlaylistItem* item = (*list)[index]; if(item) { MetaData metadata = item->GetMetaData(); int32 size = metadata.Size(); if(!size) { struct stat st; length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); if(!stat(path, &st)) size = st.st_size; else { result = kError_FileNoAccess; break; } } // figure out where to put it... uint32* memorySize; vector<PlaylistItem*>* addList; if(!useExternal) { memorySize = &internalTotal; addList = &newInternal; if(*memorySize < (uint32)size) useExternal = true; else *memorySize -= size; } if(useExternal) { memorySize = &externalTotal; addList = &newExternal; if(*memorySize < (uint32)size) break; else *memorySize -= size; } addList->push_back(item); } } // if all is well we delete old files // and temporarily download files // that are being moved from internal // to external and vice versa... if(IsntError(result)) { if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString = "Deleting files..."; function(&event, cookie); } count = origInternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origInternal[index]; if(find_if(newInternal.begin(), newInternal.end(), PlaylistItemCompare(item)) == newInternal.end()) { // need to delete it vector<PlaylistItem*>::iterator position; if((position = find_if(newExternal.begin(), newExternal.end(), PlaylistItemCompare(item))) != newExternal.end()) { // need to download it to temp file first // and then upload it to other card // in the next stage... string itemPath = item->URL(); string downloadPath = tempPath; downloadPath += DIR_MARKER_STR; downloadPath.insert(downloadPath.size(), itemPath, itemPath.rfind('/') + 1, itemPath.size()); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioInternal.RxFile(downloadPath.c_str(), rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioInternal.GetErrorID(); event.eventString = "Download failed, "; event.eventString += rioInternal.GetErrorStr(); function(&event, cookie); } if(rioInternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } length = _MAX_PATH; FilePathToURL(downloadPath.c_str(), path, &length); (*position)->SetURL(path); } string::size_type pos = item->URL().rfind("/") + 1; const char* cp = item->URL().c_str(); if(!rioInternal.RemoveFile(cp + pos)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioInternal.GetErrorID(); event.eventString = "Delete failed, "; event.eventString += rioInternal.GetErrorStr(); function(&event, cookie); } result = kError_UnknownErr; break; } delete item; origInternal[index] = NULL; } } if(IsntError(result)) { count = origExternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origExternal[index]; if(find_if(newExternal.begin(), newExternal.end(), PlaylistItemCompare(item)) == newExternal.end()) { // need to delete it vector<PlaylistItem*>::iterator position; if((position = find_if(newInternal.begin(), newInternal.end(), PlaylistItemCompare(item))) != newInternal.end()) { // need to download it to temp file first // and then upload it to other card // in the next stage... string itemPath = item->URL(); string downloadPath = tempPath; downloadPath += DIR_MARKER_STR; downloadPath.insert(downloadPath.size(), itemPath, itemPath.rfind('/') + 1, itemPath.size()); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioExternal.RxFile(downloadPath.c_str(), rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioExternal.GetErrorID(); event.eventString = "Download failed, "; event.eventString += rioExternal.GetErrorStr(); function(&event, cookie); } if(rioInternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } length = _MAX_PATH; FilePathToURL(downloadPath.c_str(), path, &length); (*position)->SetURL(path); } string::size_type pos = item->URL().rfind("/") + 1; const char* cp = item->URL().c_str(); if(!rioExternal.RemoveFile(cp + pos)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioExternal.GetErrorID(); event.eventString = "Delete failed, "; event.eventString += rioExternal.GetErrorStr(); function(&event, cookie); } result = kError_UnknownErr; break; } delete item; origExternal[index] = NULL; } } } } // if all is well we add new files // to each card if(IsntError(result)) { // remove NULLs caused by deletes origInternal.erase( remove(origInternal.begin(), origInternal.end(), (PlaylistItem*)NULL), origInternal.end()); origExternal.erase( remove(origExternal.begin(), origExternal.end(), (PlaylistItem*)NULL), origExternal.end()); // sync deletes back to the cards rioInternal.TxDirectory(); rioExternal.TxDirectory(); if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString = "Uploading new files..."; function(&event, cookie); } count = newInternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = newInternal[index]; if(item->URL().find("file://") != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioInternal.TxFile(path, rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioInternal.GetErrorID(); event.eventString = "Upload failed, "; event.eventString += rioInternal.GetErrorStr(); function(&event, cookie); } if(rioInternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } origInternal.push_back(new PlaylistItem(*item)); } } if(IsntError(result)) { count = newExternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = newExternal[index]; if(item->URL().find("file://") != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioExternal.TxFile(path, rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioExternal.GetErrorID(); event.eventString = "Upload failed, "; event.eventString += rioExternal.GetErrorStr(); function(&event, cookie); } if(rioExternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } origExternal.push_back(new PlaylistItem(*item)); } } } } // finally put it all in the correct order // and we should be done! if(IsntError(result)) { uint32 entryOrder[ CRIO_MAX_DIRENTRY ]; count = newInternal.size(); if(count) { for(index = 0; index < count; index++) { vector<PlaylistItem*>::iterator position; PlaylistItem* item = newInternal[index]; if((position = find_if(origInternal.begin(), origInternal.end(), PlaylistItemCompare(item))) != origInternal.end()) { //#ifdef WIN32 // distance(origInternal.begin(), position /*, entryOrder[index] */ ); //#else entryOrder[index] = distance(origInternal.begin(), position /*, entryOrder[index] */ ); //#endif } } rioInternal.SetFileOrder(entryOrder, count); } count = newExternal.size(); if(count) { for(index = 0; index < count; index++) { vector<PlaylistItem*>::iterator position; PlaylistItem* item = newExternal[index]; if((position = find_if(origExternal.begin(), origExternal.end(), PlaylistItemCompare(item))) != origExternal.end()) { //#ifdef WIN32 // distance(origExternal.begin(), position /*, entryOrder[index] */ ); //#else entryOrder[index] = distance(origExternal.begin(), position /*, entryOrder[index] */ ); //#endif } } rioExternal.SetFileOrder(entryOrder, count); } // sync uploads back to the cards rioInternal.TxDirectory(); rioExternal.TxDirectory(); } if(function) { PLMEvent event; event.type = kPLMEvent_Done; function(&event, cookie); } // clean up length = _MAX_PATH; FilePathToURL(tempPath, path, &length); strcpy(tempPath, path); count = origInternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origInternal[index]; if(item->URL().find(tempPath) != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); remove(path); } delete item; } count = origExternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origExternal[index]; if(item->URL().find(tempPath) != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); remove(path); } delete item; } URLToFilePath(tempPath, path, &length); rmdir(path); delete [] tempPath; delete [] path; } } } return result; }
Error PLS::WritePlaylist(const char* url, PlaylistFormatInfo* format, vector<PlaylistItem*>* list, PLMCallBackFunction function, void* cookie) { Error result = kError_InvalidParam; assert(url); assert(format); assert(list); if(url && format && list) { result = kError_FormatNotSupported; if(!strcasecmp("pls", format->GetExtension())) { FILE* fp = NULL; char path[_MAX_PATH]; uint32 length = sizeof(path); URLToFilePath(url, path, &length); result = kError_FileNoAccess; fp = fopen(path, "wb"); if(fp) { uint32 index; uint32 count; count = list->size(); for(index = 0; index < count; index++) { PlaylistItem* item = (*list)[index]; length = sizeof(path); if(IsError(URLToFilePath(item->URL().c_str(), path, &length))) fprintf(fp, "%s%s", item->URL().c_str(), LINE_END_MARKER_STR); else fprintf(fp, "%s%s", path, LINE_END_MARKER_STR); } fclose(fp); result = kError_NoErr; } else { int err = errno; switch(err) { case EACCES: result = kError_FileNoAccess; break; case EEXIST: result = kError_FileNoAccess; break; case EINVAL: result = kError_FileNoAccess; break; case ENOENT: result = kError_FileNoAccess; break; } } } } return result; }