Map files Q

vbimport

#1

Hey.

Can someone give me some code example of a function that’s get a directory path string something like:

MapFiles(CString sDirPath)

And recursively maps all the files to the NeroSDK.

Like the Nero express do with add file/dir for burning…

Thanks zik


#2

Hi zikman.

Here is the code I use to create my list of files to burn. As you can see if the search for the next file in the directory is a sub-directory, then the function calls itself to add the files from that sub-directory.


//	SearchPath is the 'root' directory for adding your files
//	**ppItem start as NULL
//	nLevel starts at 0

BOOL CNeroInterface::CreateIsoTree(CString SearchPath, NERO_ISO_ITEM** ppItem, int nLevel)
{
	CString		FileName;
	CString		FilePath;
	CFileFind	FileEnumerator;
	BOOL		bFound;
	CTime		CreationTime;

	*ppItem = NULL;

	bFound = FileEnumerator.FindFile(SearchPath);

	if(FALSE == bFound)
		return (0 == nLevel) ? FALSE : TRUE;

	while(bFound)
	{
		bFound = FileEnumerator.FindNextFile();
		FileName = FileEnumerator.GetFileName();
		FilePath = FileEnumerator.GetFilePath();
		FileEnumerator.GetCreationTime(CreationTime);

		if(FileEnumerator.IsDirectory())
		{	//	Found a directory
			if(("." == FileName) || (".." == FileName))
				continue;

			NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem();
			if(NULL == pNewItem)
			{
				DeleteIsoItemTree(*ppItem);
				return FALSE;
			}

			// Attach this item to the beginning of the list.
			if(NULL != *ppItem)
				pNewItem->nextItem = *ppItem;
			*ppItem = pNewItem;

			pNewItem->isDirectory = TRUE;
			time_t t = CreationTime.GetTime();
			pNewItem->entryTime = *localtime(&t);

			StoreFileName(pNewItem->fileName, pNewItem->longFileName, (LPCSTR)((LPCTSTR)FileName));

			// Create an ISO item tree at a deeper level

			BOOL bRetVal = CreateIsoTree(FilePath + "\\*.*", &pNewItem->subDirFirstItem, nLevel + 1);
			if(TRUE != bRetVal)
			{
				DeleteIsoItemTree(*ppItem);
				return FALSE;
			}

			// We don't allow empty directories. This should probably
			// be regulated by a command line switch.
			if(pNewItem->subDirFirstItem == NULL)
			{
				*ppItem = pNewItem->nextItem;
				pNewItem->nextItem = NULL;
				DeleteIsoItemTree(pNewItem);
			}
		}
		else
		{	//	Found a file
			NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem();

			if(NULL == pNewItem)
			{
				DeleteIsoItemTree(*ppItem);
				return FALSE;
			}

			StoreFileName(pNewItem->sourceFilePath,
				(char*)pNewItem->longSourceFilePath, FilePath);

			pNewItem->isDirectory = FALSE;
			time_t t = CreationTime.GetTime();
			pNewItem->entryTime = *localtime(&t);

			StoreFileName(pNewItem->fileName, pNewItem->longFileName, FileName);
			
			// Attach this item to the beginning of the list.
			if(NULL != *ppItem)
				pNewItem->nextItem = *ppItem;
			*ppItem = pNewItem;
		}
	}

	return TRUE;
}

void CNeroInterface::StoreFileName (char (&shortFilename)[252], char* psLongFilename,
									LPCSTR psFilename)
{
	// If filename can fit in the old field, store it there
	// to prevent unnecessary allocation. If not, allocate
	// a sufficient buffer to hold the string.
	int iLen = strlen(psFilename);

	if(iLen < sizeof(shortFilename))
	{
		strcpy(shortFilename, psFilename);
	}
	else
	{
		psLongFilename = new char[iLen + 1];
		if(psLongFilename != NULL)
		{
			strcpy(psLongFilename, psFilename);
		}
	}
}

void CNeroInterface::DeleteIsoItemTree(NERO_ISO_ITEM* pItem)
{
	FreeOurOwnResources (pItem);
	NeroFreeIsoItemTree (pItem);
}

void CNeroInterface::FreeOurOwnResources(NERO_ISO_ITEM* pItem)
{
	while(NULL != pItem)
	{
		NERO_ISO_ITEM* pNextItem = pItem->nextItem;

		if(pItem->isDirectory)	//	Recurse any directories
			FreeOurOwnResources(pItem->subDirFirstItem);

		if(!pItem->isReference)
		{
			delete pItem->longFileName;
			delete (char*)pItem->longSourceFilePath;
		}

		pItem = pNextItem;
	}
}

Hope this is what you were after.


#3

Many thanks it works very goog.

can you Explain a little on StoreFileName() function what’s it do and how?

Thanks zik


#4

All the function does is to decide whether the filename can fit into the fileName or longFileName member of the NERO_ISO_ITEM structure. Having re-read the API documentation though the fileName member has been deprecated and the names should now be stored in the longFileName structure member, so I will be changing my code accordingly and the function will no longer be required.


#5

thanks

i have one more q:

when i call CreateTree(CString SearchPath, NERO_ISO_ITEM** ppIsoItem, int nLevel)

but more then one time how should i create NERO_ISO_ITEM number of times??

thanks zikman


#6

You only call CreateIsoTree() once and once only from within your app. The function itself has a call to CreateIsoTree (itself) if a sub-directory is found.

The function also creates any NERO_ISO_ITEM structures for files and directories as it needs them:

NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem();

These are linked together with the pNewItem->nextItem structure member.

The following snippet of code from what was posted earlier shows this (I have added some comments)


	if(NULL != *ppItem)                                // if not the first in list
		pNewItem->nextItem = *ppItem; // make this item point
                                                                       // to the last one found
	*ppItem = pNewItem;                             // make the new item
                                                                       // the last one found

When the function returns from the call you made to CreateIsoTree your original pointer to the NERO_ISO_ITEM structure that you passed to the function will contain the entire linked list of file entries for the path you specified.


#7

ok but what if i need to burn more then one dir path:
1- c: mp
2- c:\windows

what then the function CreateIsoTree() gets only one path string


#8

I have not needed to do this myself but I guess you could make your second call to CreateIsoTree and pass the same pointer then the new files would be added to it in the same manner.


#9

somthing like this:

for(int i=0; i < 2; i++)
{

	 CreateTree(sDirPath[i], &m_niiFile, 0);
		
}

#10

Sorry, I have just realised the pointer is set to NULL in the first line of the function, *ppItem = NULL, so it will not work that way. In my app all of the files I need are stored in a particular directory structure first and then they are all under a single path.

I suppose you could remove that line of code and nullify the pointer before you do the function calls.



m_niiFile = NULL;

for(int i=0; i < 2; i++)
{

CreateTree(sDirPath[i], &m_niiFile, 0);

}

Try that and see if it works.


#11

it works very good…

mant thanks zikman.


#12

do maybe have some code example on how to save all the settings to an Image file insted of buring it?


#13

To create image files I believe that you simply use the ImageRecorder device, returned by the call to NeroGetAvailableDrivesEx, instead of the CD/DVD recorder device.


#14

As well as that you must intercept the DLG_FILESEL_IMAGE type in the UserDialog function, and have a mechanism to input the filename to be used for the image file.


#15

i can’t get it to work can you give some some code example


#16

Firstly you need to find the ImageRecorder from the list that is returned by NeroGetAvailableDrivesEx and open it for use. Here is an example of how to find it:



BOOL CNeroInterface::GetDrive()
{
	int	iDriveIndex;

//    Get list of drives

	if(NULL == (m_NeroDeviceInfos =
		NeroGetAvailableDrivesEx((NERO_MEDIA_TYPE)MEDIA_CD, NULL)))
		return FALSE;

//     Cycle through list looking for the image recorder entry

	for(iDriveIndex = 0; iDriveIndex < (int)(m_NeroDeviceInfos->nsdisNumDevInfos); iDriveIndex++) 
	{
		if((m_NeroDeviceInfos->nsdisDevInfos[iDriveIndex].nsdiCapabilities & NSDI_IMAGE_RECORDER) == NSDI_IMAGE_RECORDER)
		{
			break;
		}
	}

//      Check if we found it or got to the end of the list

	if(iDriveIndex < (int)(m_NeroDeviceInfos->nsdisNumDevInfos))
	{

//      Attempt to open image recorder device

		m_NeroDeviceHandle = NeroOpenDevice(&m_NeroDeviceInfos->nsdisDevInfos[iDriveIndex]);
		if(NULL == m_NeroDeviceHandle) 
		{
			MessageBox("Error whilst opening image recorder");
			return FALSE;
		}
	}

//    Drive found and opened successfully

	return TRUE;
}

m_NeroDeviceHandle and m_NeroDeviceInfos are declared in the header file as:

NERO_DEVICEHANDLE m_NeroDeviceHandle;
NERO_SCSI_DEVICE_INFOS* m_NeroDeviceInfos;

Now build your image as if you were going to burn a regular CD/DVD. When you call the NeroBurn function it will use the UserDialog callback to ask for a filename for the image file. This code is taken directly from the NeroFiddles example. The case we are interested in is DLG_FILESEL_IMAGE. The example opens the file selection dialog box allowing the user to enter the filename:


NeroUserDlgInOut NERO_CALLBACK_ATTR CNeroFiddlesDlg::UserDialog(void *pUserData, NeroUserDlgInOut type, void *data)
{
  // handling of messages that require the user to perform an action
  // for reasons of brevity we only deal with the messages that 
  // are absolutely mandatory for this application

  switch (type)
  {
    case DLG_AUTO_INSERT:
      return DLG_RETURN_CONTINUE;
      break;
    case DLG_DISCONNECT_RESTART:
      return DLG_RETURN_ON_RESTART;
      break;
    case DLG_DISCONNECT:
      return DLG_RETURN_CONTINUE;
      break;
    case DLG_AUTO_INSERT_RESTART:
      return DLG_RETURN_EXIT;
      break;
    case DLG_RESTART:
      return DLG_RETURN_EXIT;
      break;
    case DLG_SETTINGS_RESTART:
      return DLG_RETURN_CONTINUE;
      break;
    case DLG_OVERBURN:
      return DLG_RETURN_TRUE;
      break;
    case DLG_AUDIO_PROBLEMS:
      return DLG_RETURN_EXIT;
      break;
    case DLG_FILESEL_IMAGE:
      {
        // create filter for image files

        static char BASED_CODE szFilter[] = "Image Files (*.nrg)|*.nrg|All Files (*.*)|*.*||";

        // create a CFileDialog object. 
        // usage : CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL,
        //                      DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL,
        //                      CWnd* pParentWnd = NULL );
        //
        // bOpenFileDialog = TRUE, create a File Open dialog 
        // lpszDefExt = NULL, do not automatically append a file extension
        // dwFlags = OFN_OVERWRITEPROMPT, makes no sense during file open,
        //           just in case we decide to use File Save later
        // szFilter = "Image Files (*.nrg)|*.nrg|All Files (*.*)|*.*||"
        // pParentWnd = ((CNeroFiddlesDlg*)pUserData), our current Dialog window is the parent

        CFileDialog dlgOpen(TRUE, NULL, "test.nrg", OFN_OVERWRITEPROMPT, szFilter, ((CNeroFiddlesDlg*)pUserData));

        // check how the dialog was ended

        if (dlgOpen.DoModal() == IDOK)
        {
          // user pressed "OK", copy the file name to the data parameter

          strcpy((char*)data,dlgOpen.GetPathName());

          // proceed with the burn process

          return DLG_RETURN_TRUE; 
        }
        else
        {
          // user canceled, do not proceed with the burn process

          return DLG_BURNIMAGE_CANCEL;
        }
      }
      break;
    case DLG_WAITCD:
    {
      NERO_WAITCD_TYPE waitcdType = (NERO_WAITCD_TYPE) (int)data;
	  char *waitcdString = NeroGetLocalizedWaitCDTexts (waitcdType);
      ((CNeroFiddlesDlg*)pUserData)->AppendString(waitcdString);
	  NeroFreeMem(waitcdString);
      return DLG_RETURN_EXIT;
      break;
    }
    default:
      break;
  }

  // default return value, in case we forgot to handle a request
  
  return DLG_RETURN_EXIT;
}

Hope this helps