Burning more than one file at a time

I have two questions really :

  1. How do I copy more than one file at a time to CD?
    I have looked on the following link : Chaining
    and the following is what I’ve come up with:

CreateTree(const CList<CString, CString>& listOfFiles)
{

	ZeroMemory(m_niiFile, sizeof(m_niiFile));

	// now create the structure that will contain all files

	POSITION pos = listOfFiles.GetHeadPosition();
	int nCount =0;
	
             while (pos != NULL)
	{
		CString strFile = listOfFiles.GetNext(pos);

		m_niiFile[nCount] = NeroCreateIsoItem();

		if (m_niiFile[nCount] == NULL)
		{
			TRACE("Problem
");
		}
		else
		{
			m_niiFile[nCount]->longFileName = strFile.GetBuffer(strFile.GetLength());
			m_niiFile[nCount]->longSourceFilePath = strFile.GetBuffer(strFile.GetLength());
			m_niiFile[nCount]->isDirectory=FALSE;
			m_niiFile[nCount]->isReference=FALSE;

			m_niiFile[nCount]->nextItem=m_niiFile[nCount+1];
		}

		nCount++;
	}
	m_niiFile[nCount-1]->nextItem = NULL;	// not interested in this.
	// Create root item
	m_RootItem = NeroCreateIsoItem();
	m_RootItem->longFileName = "Johhnyb";
	m_RootItem->isDirectory = true;
	m_RootItem->nextItem = m_niiFile[0];

	// set up CD informational data

	m_WriteCD.nwcdpCDStamp=NULL;
	m_WriteCD.nwcdArtist=NULL;
	m_WriteCD.nwcdTitle=NULL;
	m_WriteCD.nwcdCDExtra=FALSE;
	m_WriteCD.nwcdNumTracks=0;
	m_WriteCD.nwcdMediaType = MEDIA_CD;  // all files really

The problem with this code is that no files are written whatsoever. However, if I move the code that creates the root item above the while…loop then only the folder is created on CD. Anyone know why? :confused:

Type type definitions for m_niiFile and m_RootItem is NERO_ISO_ITEM*. One can assume that listOfFiles contains the number of files and are correct as I’ve checked.

The following is my calls before I call NeroBurn :


m_WriteCD.nwcdIsoTrack = NeroCreateIsoTrackEx(m_RootItem,"Data Backup", NCITEF_CREATE_ISO_FS|NCITEF_USE_JOLIET);

int iRes = 0;

AfxMessageBox("Starting Burn
");
iRes = NeroBurn(m_ndhDeviceHandle, NERO_ISO_AUDIO_CD, &m_WriteCD,NBF_WRITE|NBF_DETECT_NON_EMPTY_CDRW, 0, &m_npProgress);

  1. How do I get the filenames that are being copied (burned) to disk at that time so that I can display the filenames on a dialog as they’re being copied. It’d also be useful to know for testing too as I have only a few CD’s left! :smiley:

Kind regards

John

Please find below the revised code as the previous code was incorrect :


CreateTree(const CList<CString, CString>& listOfFiles)
{
	m_niiFile = new NERO_ISO_ITEM[listOfFiles.GetCount()];
	// Create root item
	m_RootItem = NeroCreateIsoItem();
	m_RootItem->longFileName = "Johhnyb";
	m_RootItem->isDirectory = true;
	m_RootItem->nextItem = &m_niiFile[0];

	// now create the structure that will contain all files
	POSITION pos = listOfFiles.GetHeadPosition();
	int nCount =0;
	while (pos != NULL)
	{
		CString strPathname = listOfFiles.GetNext(pos); // this includes the Path and File
		m_niiFile[nCount] = *NeroCreateIsoItem();
		CString strFilename = strPathname.Right(strPathname.GetLength() - strPathname.ReverseFind('\\')-1);  // Just the filename


		if (&m_niiFile[nCount] == NULL)
		{
			TRACE("Problem
");
		}
		else
		{
			m_niiFile[nCount].longFileName = strFilename.GetBuffer(strFilename.GetLength());
			m_niiFile[nCount].longSourceFilePath = strPathname.GetBuffer(strPathname.GetLength());
			m_niiFile[nCount].isDirectory=FALSE;
			m_niiFile[nCount].isReference=FALSE;

			m_niiFile[nCount].nextItem=&m_niiFile[nCount+1];
		}

		nCount++;
	}
	m_niiFile[nCount-1].nextItem = NULL;	// not interested in this.

	// set up CD informational data
	m_WriteCD.nwcdpCDStamp=NULL;
	m_WriteCD.nwcdArtist=NULL;
	m_WriteCD.nwcdTitle=NULL;
	m_WriteCD.nwcdCDExtra=FALSE;
	m_WriteCD.nwcdNumTracks=0;
	m_WriteCD.nwcdMediaType = MEDIA_CD;  // all files really

}

This time, Nero is coming back with NEROAPI_BURN_FAILED flag.
I have no idea why this is so can someone point me in the right direction?

Kind regards

John

Hi John

What I did find in your code at a first glance:

  1. As far as I interpret the Nero SDK documentation, m_niiFile[nCount]->longFileName should contain the file name, not the whole file path. Even if your solution works, it might not be compatible with future versions.

  2. The following line will appear funny to you once you think about it once again:

m_niiFile[nCount]->nextItem=m_niiFile[nCount+1];

Well, where is m_niiFile[nCount+1] actually pointing to? You have not yet created the next item, so you can not assign the previous item a pointer to the next item :wink:
Edit: And what I just saw as of the writing of (5): ->nextItem should point to an item, not assign an item. Did this code really compile fine?

  1. The long source file path is of type “const char ", so you do not need to provide a "char”. Just assign static_cast(strFile) (but see the next item beforehand).

  2. BUT if you reread the documentation of CString::GetBuffer(), you’ll see that this approach is most likely not working at all:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wcemfc4/html/aflrfcstringcolcolgetbuffer.asp
The buffer memory will be freed automatically when the CString object is destroyed.

So it all comes down to this: On every iteration of and when the program leaves the “while (pos != NULL)” loop, your “CString strPathname” and “CString strFilename” will be destroyed. With them, the requested buffer will also be destroyed. The result is that the created NERO_ISO_ITEMs are pointing to garbage memory.
I just wonder why you didn’t get an access violation or similar on NeroCreateIsoTrackEx…

  1. One more thing: Did I saw the dereferencing operator in this line?
m_niiFile[nCount] = *NeroCreateIsoItem();

Assignment of the NERO_ISO_ITEM structure can not be done this way. Your array should really hold pointers to the created NERO_ISO_ITEMs. You will also be unable to destroy the ISO tree if you just assign the object instead of the object pointer. And by the way: Where do you and how will you ever call NeroFreeIsoItem or NeroFreeIsoItemTree anyway? You do not store the pointers to the created items, so you got memory leaks which will be reported by the Nero SDK when you call NeroDone().

Thanx for your reply oliver.

I realised this later on yesterday evening and I’ve now changed it to:


CString* strPathname = new CString(listOfFiles.GetNext(pos)); // pathname + filename

CString* strFilename = new CString(strPathname->Right(strPathname->GetLength() - strPathname->ReverseFind('\\')-1)); // just the filename

  1. The following line will appear funny to you once you think about it once again:
m_niiFile[nCount]->nextItem=m_niiFile[nCount+1];

I spotted that also and changed the code, after creating my NeroCreateIsoItem() for all elements :


for (int nElement = 0; nElement < nCount; nElement++)
{
      m_niiFile[nElement].nextItem = &m_niiFile[nElement+1];
}

The above code works as is intended as I’ve viewed the data in debug mode.

  1. BUT if you reread the documentation of CString::GetBuffer(), you’ll see that this approach is most likely not working at all:
    So it all comes down to this: On every iteration of and when the program leaves the “while (pos != NULL)” loop, your “CString strPathname” and “CString strFilename” will be destroyed. With them, the requested buffer will also be destroyed. The result is that the created NERO_ISO_ITEMs are pointing to garbage memory.
    I just wonder why you didn’t get an access violation or similar on NeroCreateIsoTrackEx…

See code in point 1).

  1. One more thing: Did I saw the dereferencing operator in this line?
m_niiFile[nCount] = *NeroCreateIsoItem();

Assignment of the NERO_ISO_ITEM structure can not be done this way. Your array should really hold pointers to the created NERO_ISO_ITEMs. You will also be unable to destroy the ISO tree if you just assign the object instead of the object pointer. And by the way: Where do you and how will you ever call NeroFreeIsoItem or NeroFreeIsoItemTree anyway? You do not store the pointers to the created items, so you got memory leaks which will be reported by the Nero SDK when you call NeroDone().

Your point is correct, in that I’m exepriencing memory leaks from the NERO API and has got me stumped because if I do the following :


	m_niiFile = new NERO_ISO_ITEM[listOfFiles.GetCount()];

if I create m_niiFile as an array instead of creating it dynamically then the following works, but as I’m creating it dynamically…


            m_niiFile[nCount] = NeroCreateIsoItem();  // compiler error

but…


            m_niiFile[nCount] = *NeroCreateIsoItem();  // causes memory leaks

I have got the Burning application to work in that it copies the intended files but, as you quite rightly pointed out, I’m getting memory leaks from, I guess, NeroCreateIsoItem().

Any further ideas? I’ve viewed your code :
Nero API Example, but your example only creates NERO_ISO_ITEM’s on the stack, and not the heap. Does the Nero API ensure that NERO_ISO_ITEM can only be created on the stack?

Regards

John

The Nero API provides methods for creation and destruction of NERO_ISO_ITEMs. We cannot tell where and how the Nero API allocates memory for the items, and we do not have to mess up with it. Any other usage, even if it works fine at the moment on your computer with your Nero installation, is not guaranteed to be compatible.

Note that file system delimiter may also be a forward slash (you are looking for a backslash only).

You can create m_niiFile[] as an static array or dynamic array (or whatever container), but you should use an container of pointers instead of objects, e.g.

// Create a static array of 200 NERO_ISO_ITEM pointers.
NERO_ISO_ITEM *m_niiFile[200];
memset(m_niiFile, 0, sizeof(m_niiFile));

// Assign an item to the array.
m_niiFile[0] = NeroCreateIsoItem();
assert(m_niiFile[0]);

// Delete the created NERO_ISO_ITEM.
NeroFreeIsoItem(m_niiFile[0]);
m_niiFile[0] = NULL;
// Create a dynamically sized array of 200 NERO_ISO_ITEM pointers.
NERO_ISO_ITEM ** prgpItem = new NERO_ISO_ITEM*[200];
memset(prgpItem, 0, sizeof(*prgpItem)*200);

// Assign an item to the array.
prgpItem[0] = NeroCreateIsoItem();
assert(prgpItem[0]);

// Delete the created NERO_ISO_ITEM.
NeroFreeIsoItem(prgpItem[0]);
prgpItem[0] = NULL;

// Delete the dynamically sized array.
delete [] prgpItem;
// Create a vector of NERO_ISO_ITEMs.
std::vector<NERO_ISO_ITEMS*> vecItems;

// Create a new ISO item and push it to the vector.
vecItems.push_back(NeroCreateIsoItem());

// Access  the last added ISO item.
vecItems.back().longFileName = "foo";

// Delete all created ISO items.
for (std::vector<NERO_ISO_ITEMS*>::iterator it = vecItems.begin(); it != vecItems.end(); ++it)
{
  NeroFreeIsoItem(*it);
  *it = NULL;
}

EDIT: Got bugs in the memset(…) lines, fixed.

Hi Oliver,
Just thought I’d say thankyou for the help that you’ve given me, its proved to be invaluable.

Kind Regards

John

You’re welcome - and thank you for your feedback!

Best Regards

Oliver

Thanks for all of U!

hi, i am using nero for the past 3 years and it is really fantastic
the problem am facing now is that i have some ISOs for games on my PC where some files (normally .cab) are 1.8 or even 2.5 gegas.
is there a way that i can put these on a cd, or even split them on 2 or more cds?

please note that i am not specilaist so if you please use simple language