static void import_tool(GtkWidget *w, GTKMusicBrowser *p) { FileSelector *filesel = new FileSelector(p->GetContext(),"Import a Track or Playlist into My Music"); if (filesel->Run()) { FAContext *m_context = p->GetContext(); char *returnpath = filesel->GetReturnPath(); char *filereturn = strdup_new(returnpath); if (filereturn) { char *first = strtok(filereturn, "\n"); while (first) { char *ext = m_context->player->GetExtension(first); uint32 length = strlen(first) + 10; char *tempurl = new char[length]; if (IsntError(FilePathToURL(first, tempurl, &length))) { if (ext && m_context->plm->IsSupportedPlaylistFormat(ext)) p->ImportPlaylist(tempurl); else if (ext && m_context->player->IsSupportedExtension(ext)) { PlaylistItem *plist = new PlaylistItem(tempurl); m_context->plm->RetrieveMetaDataNow(plist); m_context->catalog->WriteMetaDataToDatabase(tempurl, plist->GetMetaData()); m_context->catalog->AddSong(tempurl); delete plist; } } delete [] tempurl; delete ext; first = strtok(NULL, "\n"); } delete [] filereturn; } } delete filesel; }
void VorbisLMC::DecodeWork() { void *pOutBuffer; Error Err; int32 iValue; int32 section, ret; OutputInfo *info; vorbis_info *vi; uint32 bytesCopied, bytesPerFrame; int bitrateLoops = 0; assert(m_pPmi); assert(m_pPmo); m_pSleepSem->Wait(); m_pPmi->Wake(); Err = CanDecode(); if (Err == kError_Interrupt) return; if (Err != kError_NoErr) { m_pContext->log->Error("CanDecode returned false.\n"); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } Err = ExtractMediaInfo(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("ExtractMediaInfo failed: %d\n", Err); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } if (!m_bInit) { Err = InitDecoder(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("Initializing the decoder failed: %d\n", Err); ReportError("Initializing the decoder failed."); return; } } m_pContext->prefs->GetPrefInt32(kDecoderThreadPriorityPref, &iValue); m_decoderThread->SetPriority(iValue); bytesCopied = 0; bytesPerFrame = 1; for (m_frameCounter = 0; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); if (m_bExit) break; } if (m_newPos >= 0) { ov_time_seek(&m_vf, (double)(m_newPos / iFramesPerSecond)); m_frameCounter = m_newPos - 1; m_newPos = -1; bytesCopied = bytesPerFrame; } if (bytesCopied >= bytesPerFrame) { m_frameCounter += bytesCopied / bytesPerFrame; bytesCopied %= bytesPerFrame; ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); bitrateLoops++; if (bitrateLoops == iBitrateLoopsPerUpdate && m_decodeInfo.sendInfo) { int b; b = ov_bitrate_instant(&m_vf), vi = ov_info(&m_vf, -1); VorbisInfoEvent *mie = new VorbisInfoEvent(b, vi->channels, vi->rate, 1. / (float)iFramesPerSecond); m_pTarget->AcceptEvent(mie); bitrateLoops = 0; } } Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err == kError_Interrupt) { break; } if (Err == kError_BufferTooSmall) { if (Sleep()) break; continue; } if (Err != kError_NoErr) { ReportError(szFailWrite); m_pContext->log->Error("LMC: Cannot write to eventbuffer: %s (%d)\n", m_szError, Err); break; } section = -1; ret = ov_read(&m_vf, (char *)pOutBuffer, iDecodeBlockSize, 0, 2, 1, §ion); if (ret == 0) { m_pOutputBuffer->EndWrite(0); break; } if (section != m_section) { vi = ov_info(&m_vf, -1); info = new OutputInfo; info->bits_per_sample = 16; info->number_of_channels = m_channels = vi->channels; info->samples_per_second = m_rate = vi->rate; info->samples_per_frame = vi->rate / iFramesPerSecond; info->max_buffer_size = 16384; m_frameCounter = 0; bytesCopied = 0; bytesPerFrame = (vi->rate / iFramesPerSecond) * sizeof(ogg_int16_t) * vi->channels; m_section = section; m_pOutputBuffer->EndWrite(0); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOInitEvent(info)); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err != kError_NoErr) { assert(0); } vorbis_comment *comment; comment = ov_comment(&m_vf, -1); if (comment) { PlaylistItem *plItem = m_pContext->plm->GetCurrentItem(); if (plItem) { MetaData mdata = plItem->GetMetaData(); string iso; char *temp; temp = vorbis_comment_query(comment, "title", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetTitle(iso); } temp = vorbis_comment_query(comment, "artist", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetArtist(iso); } temp = vorbis_comment_query(comment, "album", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetAlbum(iso); } temp = vorbis_comment_query(comment, "tracknumber", 0); if (temp) mdata.SetTrack(atoi(temp)); plItem->SetMetaData(&mdata); m_pContext->target->AcceptEvent( new PlaylistCurrentItemInfoEvent(plItem, m_pContext->plm)); } } } if(ret <0) ret=0; // hole/error in data - we can safely ignore this m_pOutputBuffer->EndWrite(ret); bytesCopied += ret; } ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent()); ov_clear(&m_vf); return; }
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; }