📄 hxbackend.cpp
字号:
(void**)&m_pPromptService); pServiceManager->GetServiceByContractID("@mozilla.org/xpcom/memory-service;1", NS_GET_IID(nsIMemory), (void**)&m_pMemory); /* Get the component manager from the service manager */ rv = pServiceManager->QueryInterface(NS_GET_IID(nsIComponentManager), (void**) &pComponentManager); if(pComponentManager && NS_SUCCEEDED(rv)) { pComponentManager->CreateInstanceByContractID(NS_ISCRIPTABLEUNICODECONVERTER_CONTRACTID, NULL, NS_GET_IID(nsIScriptableUnicodeConverter), (void**)&m_pUConv); pComponentManager->CreateInstanceByContractID(NS_TIMER_CONTRACTID, NULL, NS_GET_IID(nsITimer), (void**)&m_pTimer); if(!m_pTimer) { /* Try to get an old-style mozilla 1.0-1.2 timer */ pComponentManager->CreateInstanceByContractID(NS_TIMER_CONTRACTID, NULL, NS_GET_IID(nsIScriptableTimer), (void**)&m_pObsoleteTimer); } NS_RELEASE(pComponentManager); } NS_RELEASE(pServiceManager); } // Step 2: Initialize services if(m_pUConv) { m_pUConv->SetCharset("us-ascii"); } m_bPlayerShutdown = PR_FALSE; return NS_OK;}nsresult CHXPlayerBackend::OpenEmbeddedPlayer(NPP instance){ int apisockets[2], cbsockets[2]; FindPlayerState findPlayerState = FIND_PLAYER_STATE_INIT; while(findPlayerState != FIND_PLAYER_STATE_FAILED) { const char* szAppName; switch(findPlayerState) { case FIND_PLAYER_STATE_INIT: /* New state */ findPlayerState = FIND_PLAYER_STATE_OVERRIDE; szAppName = getenv("HELIX_PLUGIN_PLAYER_OVERRIDE"); if(szAppName) { break; } /* failed to find an override, fall through */ case FIND_PLAYER_STATE_OVERRIDE: findPlayerState = FIND_PLAYER_STATE_REALPLAY; szAppName = "realplay"; break; case FIND_PLAYER_STATE_REALPLAY: findPlayerState = FIND_PLAYER_STATE_HXPLAY; szAppName = "hxplay"; break; case FIND_PLAYER_STATE_HXPLAY: case FIND_PLAYER_STATE_FAILED: default: findPlayerState = FIND_PLAYER_STATE_FAILED; szAppName = NULL; break; } if(findPlayerState == FIND_PLAYER_STATE_FAILED) { break; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, apisockets) < 0) { perror("socketpair"); return NPERR_GENERIC_ERROR; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, cbsockets) < 0) { perror("socketpair"); close(apisockets[0]); close(apisockets[1]); return NPERR_GENERIC_ERROR; } // make sure these fds stay open across exec fcntl(apisockets[1], F_SETFD, 0); fcntl(cbsockets[1], F_SETFD, 0); m_nChildPid = fork(); if(m_nChildPid < 0) { perror("fork"); close(apisockets[0]); close(apisockets[1]); close(cbsockets[0]); close(cbsockets[1]); return NS_ERROR_FAILURE; } else if(m_nChildPid == 0) { // we are the child. int result; printf("Calling %s\n", szAppName);#if 0 char c = 0; printf("Attach to child %d\n", getpid()); while(c == 0) { }#endif close(apisockets[0]); close(cbsockets[0]); char apiSd[20]; sprintf(apiSd, "%d", apisockets[1]); char cbSd[20]; sprintf(cbSd, "%d", cbsockets[1]); if (m_pTimer || m_pObsoleteTimer) { /* We have a timer callback, include --callbacks flag */ result = execlp(szAppName, szAppName, "--embedded", apiSd, "--callbacks", cbSd, NULL); } else { /* No timer service -- disable callbacks */ result = execlp(szAppName, szAppName, "--embedded", apiSd, NULL); } if (result < 0) { int nExitCode = 0; switch(errno) { case ENOENT: nExitCode = EXIT_CODE_HXPLAY_NOT_FOUND; break; default: nExitCode = EXIT_CODE_UNKNOWN; break; } // we couldn't exec hxplay. close(apisockets[1]); close(cbsockets[1]); // Use _exit instead of exit to avoid affecting open // mozilla file descriptors _exit(nExitCode); } } // we are the parent m_fdApi = apisockets[0]; m_fdCallback = cbsockets[0]; /* The embedded player, if any, now owns these. Close our side. */ close(apisockets[1]); close(cbsockets[1]); /* Embedded player is now open until proved otherwise */ m_bEmbeddedPlayerOpen = PR_TRUE; // Check for protocol version char szRequest[32]; nsresult result; int iPlayerVersion = -1; int nLen; nLen = snprintf(szRequest, sizeof(szRequest), "Version %d\n", m_iBackendVersion); result = SendMessage(szRequest, nLen); if(NS_SUCCEEDED(result)) { int iReturnCode; char *pMsg = NULL; result = ReceiveMessage(&pMsg); if(NS_SUCCEEDED(result)) { sscanf(pMsg, "%d, %d", &iReturnCode, &iPlayerVersion); free(pMsg); if(NS_SUCCEEDED(iReturnCode)) { if(iPlayerVersion == m_iBackendVersion) { /* found a suitable player */ break; } else { CloseEmbeddedPlayer(PR_TRUE); } } else { CloseEmbeddedPlayer(PR_TRUE); } } else { CloseEmbeddedPlayer(PR_FALSE); } } else { CloseEmbeddedPlayer(PR_FALSE); } } // while(m_findPlayerState != FIND_PLAYER_STATE_FAILED) if(findPlayerState == FIND_PLAYER_STATE_FAILED) { ShowError("Could not find an appropriate hxplay or realplay in the " "system path to use as an embedded player", instance); /* Shutdown will clean up after Init() */ Shutdown(PR_FALSE); return NS_ERROR_FAILURE; } /* Allocate initial buffer space */ m_nCallbackBufLen = 1024; m_pCallbackBuf = (char*)malloc(m_nCallbackBufLen * sizeof(char)); StartCallbackTimer(); return NS_OK; } void CHXPlayerBackend::ShowError(const char *szError, NPP instance){ nsIDOMWindow *pDomWindow = NULL;#ifdef DEBUG /* Sanity check to make sure the error doesn't contain newlines. nsIPromptService can handle 'em, but javascript alert cannot. */ assert(strchr(szError, '\n') == NULL);#endif if(!instance) { if(m_nPlayerCount > 0) { /* Get the instance of the first player plugin */ instance = m_pPlayersList[0]->GetInstance(); } } if(instance) { PRUnichar *pUnicodeTitle = NULL; PRUnichar *pUnicodeMessage = NULL; NPN_GetValue(instance, NPNVDOMWindow, &pDomWindow); if(m_pPromptService && m_pUConv && m_pMemory && pDomWindow) { m_pUConv->ConvertToUnicode("Helix DNA Plugin Error", &pUnicodeTitle); m_pUConv->ConvertToUnicode(szError, &pUnicodeMessage); } if(pUnicodeTitle && pUnicodeMessage && m_pPromptService && m_pMemory && pDomWindow) { /* Cancel the callback timer while the alert dialog is up to prevent a race (eg, the timer callback can call Shutdown(), which would destroy resources that are used below) */ PRBool bRestartCallbackTimer = m_bCallbackTimerRunning; StopCallbackTimer(); m_pPromptService->Alert(pDomWindow, pUnicodeTitle, pUnicodeMessage); if(bRestartCallbackTimer) { StartCallbackTimer(); } } else { /* Fall back to printing error to standard out, and attempting a javascript alert */ char *szJavaScriptAlert; asprintf(&szJavaScriptAlert, "javascript:alert(\"%s\")", szError); NPN_GetURL(instance, szJavaScriptAlert, "_self"); free(szJavaScriptAlert); } if(pUnicodeTitle) { m_pMemory->Free(pUnicodeTitle); } if(pUnicodeMessage) { m_pMemory->Free(pUnicodeMessage); } } fprintf(stderr, "%s\n", szError); if(pDomWindow) { NS_IF_RELEASE(pDomWindow); }}nsresult CHXPlayerBackend::ReadGenericResponse(PRBool* retval){ // just reads a generic response code char *pMsg; nsresult result; *retval = PR_FALSE; result = ReceiveMessage(&pMsg); if(NS_FAILED(result)) { return result; } if(sscanf(pMsg, "%d", retval) != 1) { result = NS_ERROR_FAILURE; } free(pMsg); return result;}void CHXPlayerBackend::CloseEmbeddedPlayer(PRBool bSendShutdownCommand){ nsresult result; PRBool retval; char *pMsg; int nLen; int i; if(!m_bEmbeddedPlayerOpen) { return; } if(bSendShutdownCommand) { /* Tell the player to quit */ pMsg = "Shutdown\n"; nLen = strlen(pMsg); result = SendMessage(pMsg, nLen); if(NS_SUCCEEDED(result)) { result = ReadGenericResponse(&retval); /* Ignore retval... */ } } /* Make sure the player exits */ int nStatus = 0; PRBool bExited = PR_FALSE; if(m_nChildPid) { for(i = 0; i < 10; i++) { /* Give the player 2 seconds to exit */ pid_t pidExited = 0; pidExited = waitpid(m_nChildPid, &nStatus, WNOHANG); if(WIFEXITED(nStatus) && pidExited) { bExited = PR_TRUE; break; } usleep(200); } if(!bExited) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -