/* This file contains the implementation of the CDummyRoboDriver class. */ #include "DummyDriver.h" #include "CCOMSerial.h" #include "AbstractUserDialog.h" /** Synchronize access to common GUI interface since it is access from our print thread too. */ #define CN_LOCK if (m_pRoboMutex != NULL) m_pRoboMutex->Lock() #define CN_UNLOCK if (m_pRoboMutex != NULL) m_pRoboMutex->Unlock() CDummyRoboDriver::CDummyRoboDriver(IRoboCommNode *commnode) { /** Initialize our members. */ m_pCommNode = commnode; m_pRoboMutex = (m_pCommNode != NULL) ? m_pCommNode->CreateMutex() : NULL; m_pPrintThread = NULL; m_pCommInterface = (m_pCommNode != NULL) ? m_pCommNode->GetSerialInterface() : NULL; m_eCurrentDiscPos = IRoboCommNode::ERLN_INPUT; m_bShowInfoMessage = TRUE; m_bPrintBeforeBurn = (m_pCommNode != NULL) ? m_pCommNode->GetConfigurationValueBOOL(CONFIG_PRINTBEFOREBURN, DEFAULTCONFIG_PRINTBEFOREBURN) : DEFAULTCONFIG_PRINTBEFOREBURN; m_bParallelizePrinting = (m_pCommNode != NULL) ? m_pCommNode->GetConfigurationValueBOOL(CONFIG_PARALLELIZE, DEFAULTCONFIG_PARALLELIZE) : DEFAULTCONFIG_PARALLELIZE; m_bIsTesting = FALSE; /** Configure the COM interface, although we don't use it here. */ if((m_pCommInterface != NULL) && (m_pCommInterface->GetPortType() == PORT_SERIAL)) static_cast(m_pCommInterface)->SetConfiguration(14400, 8, CCOMSerial::CPARITY_NO, CCOMSerial::STOPBITS_ONE); /** Up interface version 4 we can use some new communication node methods. */ m_bHasNewInterface = (NERO_PLUGIN_GetInterfaceVersion() >= 4); /** We just don't paralllelize if printing should be done before burning. */ if(m_bPrintBeforeBurn) m_bParallelizePrinting = FALSE; } CDummyRoboDriver::~CDummyRoboDriver() { /** Wait for print thread before we destroy our driver, to be sure the robo is idle. */ WaitForPrintThread(); if(m_pRoboMutex != NULL) delete m_pRoboMutex, m_pRoboMutex = NULL; } BOOL CDummyRoboDriver::InitBurn() { BOOL bResult = TRUE; if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "InitBurn is called.\n" \ "Do some INITIALIZATION like RESETING robot here.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } return bResult; } BOOL CDummyRoboDriver::PreBurn() { BOOL bResult = TRUE; if((m_pCommNode != NULL) && (m_bShowInfoMessage)) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "PreBurn is called.\n" \ "Now you can PRINT label before burning it.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } return bResult; } BOOL CDummyRoboDriver::InsertCD() { BOOL bResult = TRUE; if(m_pCommNode != NULL) { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "InsertCD is called.\n" \ "Send move command to your robot.\n" \ "MOVE the disc to RECORDER or PRINT it before\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } CUserDialogHandle *pDialog = NULL; /** Check if printing label is possible. */ if(m_bPrintBeforeBurn && m_pCommNode->LabelPrintEnabled()) { WaitForPrintThread(); CN_LOCK; pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_INPUT, IRoboCommNode::ERLN_PRINTER); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; m_eCurrentDiscPos = IRoboCommNode::ERLN_PRINTER; if(m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE) { CN_LOCK; pDialog = m_pCommNode->CreatePrintCoverDialog(); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; if(m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE) pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_PRINTER, IRoboCommNode::ERLN_RECORDER); else bResult = FALSE; } else bResult = FALSE; } else { CN_LOCK; pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_INPUT, IRoboCommNode::ERLN_RECORDER); CN_UNLOCK; } if(bResult) { m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); m_eCurrentDiscPos = IRoboCommNode::ERLN_RECORDER; bResult = m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE; } CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; } else bResult = FALSE; return bResult; } BOOL CDummyRoboDriver::RemoveNonWriteableCD() { BOOL bResult = TRUE; if(m_pCommNode != NULL) { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "RemoveNonWriteableCD is called.\n" \ "Send move command to your robot.\n" \ "MOVE the disc to WASTE bin because it can not be burned.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } CN_LOCK; CUserDialogHandle *pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_RECORDER, IRoboCommNode::ERLN_WASTEBIN); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; m_eCurrentDiscPos = IRoboCommNode::ERLN_WASTEBIN; bResult = m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE; } return bResult; } BOOL CDummyRoboDriver::RemoveUntouchedCD() { BOOL bResult = TRUE; if(m_pCommNode != NULL) { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "RemoveUntouchedCD is called.\n" \ "Send move command to your robot.\n" \ "MOVE the disc back to INPUT bin because it was not burned.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } CN_LOCK; CUserDialogHandle *pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_RECORDER, IRoboCommNode::ERLN_INPUT); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; m_eCurrentDiscPos = IRoboCommNode::ERLN_INPUT; bResult = m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE; } return bResult; } BOOL CDummyRoboDriver::PostBurnOK() { BOOL bResult = TRUE; if(m_pCommNode != NULL) { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "PostBurnOK is called.\n" \ "Send move command to your robot.\n" \ "MOVE the disc to OUTPUT bin or PRINT it before.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } CUserDialogHandle *pDialog = NULL; if(!m_bPrintBeforeBurn && m_pCommNode->LabelPrintEnabled()) { WaitForPrintThread(); CN_LOCK; pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_RECORDER, IRoboCommNode::ERLN_PRINTER); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; m_eCurrentDiscPos = IRoboCommNode::ERLN_PRINTER; /** Create separate print thread, so the driver can do another tasks (e.g. insert new disc in the recorder) * during Printing. */ if(m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE) m_pPrintThread = m_pCommNode->CreateThread(PrintThreadEntry, (void*)this); else bResult = FALSE; if(!m_bParallelizePrinting /*|| m_bIsTesting*/) WaitForPrintThread(); } else { CN_LOCK; pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_RECORDER, IRoboCommNode::ERLN_OUTPUT); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); m_eCurrentDiscPos = IRoboCommNode::ERLN_OUTPUT; } if(bResult) bResult = m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE; CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; } return bResult; } BOOL CDummyRoboDriver::PostBurnFAILURE() { BOOL bResult = TRUE; if(m_pCommNode != NULL) { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "PostBurnFAILURE is called.\n" \ "Send move command to your robot.\n" \ "MOVE the disc to WASTE bin because burning failed.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } CN_LOCK; CUserDialogHandle *pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_RECORDER, IRoboCommNode::ERLN_WASTEBIN); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; m_eCurrentDiscPos = IRoboCommNode::ERLN_WASTEBIN; bResult = m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE; } return bResult; } BOOL CDummyRoboDriver::CleanUp() { BOOL bResult = TRUE; if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "CleanUp is called.\n" \ "REMOVE remaining discs from PRINTER and RECORDER.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } WaitForPrintThread(); if((m_eCurrentDiscPos == IRoboCommNode::ERLN_RECORDER) || (m_eCurrentDiscPos == IRoboCommNode::ERLN_PRINTER)) { CN_LOCK; CUserDialogHandle *pDialog = m_pCommNode->CreateMoveCDDialog(m_eCurrentDiscPos, IRoboCommNode::ERLN_WASTEBIN); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; m_eCurrentDiscPos = IRoboCommNode::ERLN_WASTEBIN; bResult = m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE; } return bResult; } BOOL CDummyRoboDriver::StartPrintLabel() { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "StartPrintLabel is called.\n" \ "PRINT the LABEL if not already done.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } return TRUE; } BOOL CDummyRoboDriver::StartRoboTest() { BOOL bResult = TRUE; m_bIsTesting = TRUE; if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "StartRoboTest is called.\n" \ "MOVE the disc USUAL WAY to check the setting.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } bResult = InsertCD() ? PostBurnOK() : FALSE; m_bIsTesting = FALSE; return bResult; } BOOL CDummyRoboDriver::ExitBurn() { if(m_bShowInfoMessage) { CUserDialogHandle *pErrorMessage = m_pCommNode->CreateMessage( "ExitBurn is called.\n" \ "CLEANUP because burning could be aborted.\n" \ "Press Cancel, so these messages will not be displayed anymore.", ROBOCOMMNODE_MSG_HINT); if(pErrorMessage != NULL) pErrorMessage->WaitForUserFeedback(); m_bShowInfoMessage = (pErrorMessage->GetFeedback() != CUserDialogHandle::DLGRESULT_CANCEL); if(pErrorMessage != NULL) delete pErrorMessage, pErrorMessage = NULL; } return WaitForPrintThread() ? CleanUp() : FALSE; } UINT CDummyRoboDriver::PrintThreadEntry(void *pData) { UINT uiResult = 1; CDummyRoboDriver *pThis = (CDummyRoboDriver*)pData; if(pThis != NULL) uiResult = pThis->PrintThread(); return uiResult; } UINT CDummyRoboDriver::PrintThread() { BOOL bResult = FALSE; if(m_pCommNode != NULL) { /** Add this thread to our list, so Nero will know to wait for it. */ if(m_bHasNewInterface) m_pCommNode->AddMyPrintThread(); CUserDialogHandle *pDialog = NULL; CN_LOCK; pDialog = m_pCommNode->CreatePrintCoverDialog(); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; if(m_bHasNewInterface ? !m_pCommNode->IsAbortedImmediate() : TRUE) { CN_LOCK; pDialog = m_pCommNode->CreateMoveCDDialog(IRoboCommNode::ERLN_PRINTER, IRoboCommNode::ERLN_OUTPUT); CN_UNLOCK; m_pCommNode->SuspendThread(SIMULATEROBOMOVEMENT_TIMEOUT); CN_LOCK; if(pDialog != NULL) delete pDialog, pDialog = NULL; CN_UNLOCK; } else bResult = FALSE; if(m_bHasNewInterface) m_pCommNode->RemoveMyPrintThread(); } return bResult ? 0 : 1; /* Return 0 on success */ } BOOL CDummyRoboDriver::WaitForPrintThread() { DWORD dwResult = 1; /* Wait for the print thread to exit */ if((m_pPrintThread != NULL) && (m_pCommNode != NULL)) { while(!m_pPrintThread->GetExitCodeThread(&dwResult)) m_pCommNode->SuspendThread(100); delete m_pPrintThread; m_pPrintThread = NULL; } return (dwResult == 0); // Everything went ok };