chxavfilestore.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,202 行 · 第 1/3 页
CPP
1,202 行
/************************************************************************
* chxavfilestore.cpp
* ------------------
*
* Synopsis:
* simple file system abstraction for manipulating files and folders;
* maintains 'root' (relative to true filesystem) 'current' folder
* state
*
* root path is stored in full form, e.g.: c:\real\media\
* folder is stored in relative form, fully specified, e.g.:
* \ = root
* \music\ = subfolder music
*
* the term 'item' (as used in this class) refers to a file or folder
* that is in the current entry list; the entry list contains a list
* of files and folders within the current folder
*
* Target:
* Symbian OS
*
*
* (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
*
************************************************************************/
// Symbian includes...
#include <coeutils.h>
#include <eikfutil.h>
#include <f32file.h> // TSwitch, CFileMan
// Helix includes...
// Include from this project...
#include "chxavfilestore.h"
#include "chxavdirectoryreader.h"
#include "chxavfileutil.h"
#include "chxavutil.h"
#include "chxavmisc.h"
#include "chxavstringutils.h"
#include "hxsym_leaveutil.h"
#include "hxsym_debug.h"
CHXAvFileStore::CHXAvFileStore()
: m_pFullPath(0)
, m_bNeedRefresh(true)
, m_pFileMan(0)
, m_pObserver(0)
, m_cbFileOp(0)
, m_suspendRefreshSem(0)
, m_bHaveOutstandingFileSystemEvent(false)
{
}
CHXAvFileStore::~CHXAvFileStore()
{
HX_DELETE(m_pFullPath);
HX_DELETE(m_pFileMan);
#if defined(ASYNC_COPYMOVE)
CancelAsyncFileOp();
#endif
m_apaLsSess.Close();
}
////////////////////////////////////////////////////////////
//
void CHXAvFileStore::ConstructL(const TDesC& root,
const TDesC& path,
bool bAutoCreateRoot)
{
m_apaLsSess.Connect();
m_fsWatcher.ConstructL();
// set callback for receiving fs event notifications
m_fsWatcher.SetEventActionL
(
MakeCommand(this, &CHXAvFileStore::OnFileSystemEvent)
);
#if defined(ASYNC_COPYMOVE)
// active object to run on asynch completion of file op
m_pFileOpCompletion =
new (ELeave) CHXAvActiveDisp<CHXAvFileStore>(this,
&CHXAvFileStore::OnFileOpAsyncComplete,
&CHXAvFileStore::OnFileOpAsyncCancel);
CActiveScheduler::Add(m_pFileOpCompletion.raw_ptr());
#endif
// create, fill out and activate the listbox
SetRootL(root, bAutoCreateRoot);
SetCurrentPathL(path);
RefreshEntryInfoL();
RFs& fs = CCoeEnv::Static()->FsSession();
m_pFileMan = CFileMan::NewL(fs, this /*observer*/);
}
////////////////////////////////////////////////////////////
// paths can be provided as relative to root (e.g., /media/myfolder/foo.rm)
// or absolute ('e:/videos/)
//
// this decides which and returns a fully specified path with drive
//
//
TFileName* CHXAvFileStore::AllocFullPathL(const TDesC& path,
const TDesC& name,
CHXAvFile::NameType type)
{
TFileName* pPath = 0;
TInt idxDrive = CHXAvFile::GetDriveIndex(path);
if(-1 != idxDrive)
{
// path has a drive; it is absolute
pPath = CHXAvFile::AllocFileNameL(path, name, type);
}
else
{
// path is relative
pPath = CHXAvFile::AllocFileNameL(GetRoot(), path, CHXAvFile::ntFolder);
CHXAvFile::AppendPath(*pPath, name, type);
}
return pPath;
}
//////////////////////////////////////////////////////////////
// return true if fullPathChild is path to file or folder immediately
// under current path
bool CHXAvFileStore::IsImmediateChild(const TDesC& fullPathChild)
{
TPtrC ptrFolder = CHXAvFile::GetParentFolder(fullPathChild);
return (0 == ptrFolder.CompareF(*m_pFullPath));
}
//////////////////////////////////////////////////////////////
// return true if fullPathParent is a parent of the current
//
bool CHXAvFileStore::IsParent(const TDesC& fullPathParent)
{
return CHXAvFile::IsSubPath(fullPathParent, *m_pFullPath);
}
////////////////////////////////////////////////////////////
// return true if the destination path matches the
// path for the given item within the current path
//
// pathDest - relative or absolute path
// idxItem - item in current path
//
bool CHXAvFileStore::IsSamePathL(const TDesC& pathDest, TInt idxItem)
{
bool bIsSame = false;
// form "pathdest" + "name associated with item in current path"
TFileName* pSrcPath = AllocFullPathL(idxItem);
AUTO_PUSH_POP_DEL(pSrcPath);
TFileName* pDestPath = AllocFullTargetPathL(pathDest, idxItem);
AUTO_PUSH_POP_DEL(pDestPath);
bIsSame = ( pSrcPath->CompareF(*pDestPath) == 0 );
return bIsSame;
}
////////////////////////////////////////////////////////////
// called when fs watcher detects an event
void CHXAvFileStore::OnFileSystemEvent()
{
DPRINTF(SYMP_FILE, ("FileStore::OnFileSystemEvent(): suspend count = %ld\n", m_suspendRefreshSem));
// flag that entry list is out of data
m_bNeedRefresh = true;
if(m_suspendRefreshSem > 0)
{
// keep track of fact that we got file system event while locked; we'll defer
// notifying observer until we become unlocked
m_bHaveOutstandingFileSystemEvent = true;
}
else
{
m_bHaveOutstandingFileSystemEvent = false;
m_eventHandler.Execute();
}
}
////////////////////////////////////////////////////////////
// path must be fully qualified absolute root path, e.g., something like:
//
// 'e:\realnetworks\media\'
// 'c:\media\'
//
// * trailing slash required
// * drive letter required
//
// can be called more than once
//
void CHXAvFileStore::SetRootL(const TDesC& path, bool bAutoCreateRoot)
{
RFs& fs = CCoeEnv::Static()->FsSession();
TInt idxDrive = CHXAvFile::GetDriveIndex(path);
if(idxDrive == -1 || !CHXAvFile::HasFolderSuffix(path))
{
// caller should ensure path suffix and valid drive
HXSYM_LEAVE(KErrBadName);
}
TInt errExist = KErrPathNotFound;
if( bAutoCreateRoot )
{
TRAP(errExist, BaflUtils::EnsurePathExistsL(fs, path));
}
else if(BaflUtils::PathExists(fs, path))
{
errExist = KErrNone;
}
// make sure root is valid by now
HXSYM_LEAVE_IF_ERR(errExist); // drive doesn't exist?
TFileName* pFullPath = new (ELeave) TFileName;
AUTO_PUSH_POP_DEL(pFullPath);
HXSYM_LEAVE_IF_ERR(CHXAvFile::GetFullPath(fs, path, *pFullPath));
m_root.Set(*pFullPath, 0, 0);
UpdateFullPathL();
HX_ASSERT(CHXAvFile::HasFolderSuffix(m_root.FullName()));
// watch for fs events; this resets watch path if we were watching previously
if( m_root.FullName().Length() > 3 )
{
m_fsWatcher.SetWatchPathL(m_root.FullName());
}
else
{
//
// specifying a root drive path like 'c:\' fails for some reason so watch
// everything in this case
//
m_fsWatcher.SetWatchPathL(KNullDesC);
}
m_fsWatcher.SetNotifyType(TNotifyType(ENotifyDir | ENotifyFile | ENotifyEntry));
m_fsWatcher.StartWatching();
m_bNeedRefresh = true;
}
////////////////////////////////////////////
// path - relative to current root path;
// leading and trailing path delimiter is optional
//
//
void CHXAvFileStore::SetCurrentPathL(const TDesC& path)
{
// we want to make sure it looks like '/folder/'
m_curPath.SetLength(0);
CHXAvFile::AppendPath(m_curPath, path, CHXAvFile::ntFolder);
DPRINTF(SYMP_FILE, ("FileStore::SetCurrentPathL(): current path '%s'\n", dbg::CharPtr(path)()));
TInt err = EikFileUtils::CheckFolder(UpdateFullPathL());
HXSYM_LEAVE_IF_ERR(err); // leave if path not found
m_bNeedRefresh = true;
HX_ASSERT(CHXAvFile::HasFolderPrefix(m_curPath));
HX_ASSERT(CHXAvFile::HasFolderSuffix(m_curPath));
}
////////////////////////////////////////////////////////////
// make sure full path refers to current folder
const TDesC& CHXAvFileStore::UpdateFullPathL()
{
// alloc fully qualified folder base path
if(!m_pFullPath)
{
m_pFullPath = CHXAvFile::AllocFileNameL(m_root.FullName(), m_curPath, CHXAvFile::ntFolder);
}
else
{
m_pFullPath->Copy(m_root.FullName());
CHXAvFile::AppendPath(*m_pFullPath, m_curPath, CHXAvFile::ntFolder);
}
return *m_pFullPath;
}
////////////////////////////////////////////
// count files (not folders) in the in the
// current entries list
TInt CHXAvFileStore::GetCurrentFolderFileCount() const
{
TInt itemCount = m_entryInfo.Nelements();
TInt fileCount = 0;
for(TInt idx = 0; idx < itemCount; ++idx)
{
if(!m_entryInfo[idx].m_entry.IsDir())
{
++fileCount;
}
}
return fileCount;
}
////////////////////////////////////////////////////
// add relevant file entries to list info
//
void CHXAvFileStore::RefreshEntryInfoHelper(const CDir* pFiles, bool bIncludeFolders)
{
HX_ASSERT(pFiles != 0);
TInt count = pFiles->Count();
for( TInt idx = 0; idx < count; ++idx )
{
const TEntry& entry = (*pFiles)[idx];
// don't add special (system, hidden) files
if(!CHXAvUtil::ShouldHideFromUser(entry)) //XXXLCM 'filter policy'
{
// note: entry.iName is stripped, e.g., 'folder'
if(entry.IsDir() && bIncludeFolders)
{
// add directory
CHXAvUtil::Append(m_entryInfo, CHXAvFile::FileInfo(entry, CHXAvFile::ftFolder));
}
else
{
// only add filetypes that we can play(e.g., 'file.rm')
TFileName* pPath = CHXAvFile::AllocFileNameL(GetFullPath(),
entry.iName);
AUTO_PUSH_POP_DEL(pPath);
CHXAvFile::FileType type = CHXAvFile::GetFileType(*pPath);
if (CHXAvFile::IsNanoPlayerFileType(type)) //XXXLCM 'filter policy'
{
CHXAvUtil::Append(m_entryInfo, CHXAvFile::FileInfo(entry, type));
}
}
}
}
}
// for RefreshSuspenderL
void CHXAvFileStore::CleanupSuspendRefresh(TAny* p)
{
CHXAvFileStore* pFs = reinterpret_cast<CHXAvFileStore*>(p);
pFs->SuspendRefresh(false);
}
////////////////////////////////////////////////////////////
//
// Call with 'true' to temporarily prevent file and dir list updates as
// well as filesystem event notifications being forwarded. This
// 'locks' the file and dir entry lists so that any indexes associated with
// current lists that are held by client remain valid.
//
// Useful in cases where you are holding on to an index while, say,
// waiting for user input before acting on the index.
//
// An alternative is to use CopyEntriesL()
//
void CHXAvFileStore::SuspendRefresh(bool bSuspend)
{
if( bSuspend )
{
++m_suspendRefreshSem;
}
else
{
--m_suspendRefreshSem;
}
DPRINTF(SYMP_FILE, ("FileStore::SuspendRefresh('%s'): suspend count = %d\n", dbg::Bool(bSuspend), m_suspendRefreshSem));
HX_ASSERT(m_suspendRefreshSem >= 0); // calls must be balanced
if(0 == m_suspendRefreshSem)
{
DPRINTF(SYMP_FILE, ("FileStore::SuspendRefresh(): exiting suspend\n"));
// we are no longer suspended; now we can forward deferred filesystem
// event notifications to observes
if( m_bHaveOutstandingFileSystemEvent )
{
DPRINTF(SYMP_FILE, ("FileStore::SuspendRefresh(): sending deferred file system event notification\n"));
OnFileSystemEvent();
}
}
}
////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?