hp webos, pdk plugin defunct in hybrid app. - webos

I have been trying to call a pdk plugin from the mojo hybrid app and have also tried the same with enyo app. In both cases my pdk plugin is shown as , Interesting thing is in case of enyo, i received the plugin_ready response which is sent after the plugin registration is complete.
in the web-os site, they mentioned that it is the issue with pdk plugin that makes it look defunct.
but i could not find a method to resolve it.
This is how my plugin looks,
PDL_bool powerCall(PDL_JSParameters *params) {
runsine();
char *reply = "Done";
PDL_JSReply(params, reply);
return PDL_TRUE;
}
int main(){
int result = SDL_Init(SDL_INIT_VIDEO);
PDL_Init(0);
PDL_RegisterJSHandler("pawar", powerCall);
PDL_JSRegistrationComplete();
PDL_CallJS("ready", NULL, 0); // this is for enyo
PDL_Quit();
SDL_Quit();
return 0;
}
please suggest me how to solve this issue. i know its a very simple task and am frustrated that its taking this long.
Thanks
Shankar

In your plugin you should enter an event loop after you call the "ready" function, and before you call the PDL_Quit() and SDL_Quit(). Not having an event loop causes the plugin process to quit right away.
Here is an example based on the "simple" app that ships with the PDK:
int main(){
int result = SDL_Init(SDL_INIT_VIDEO);
PDL_Init(0);
PDL_RegisterJSHandler("pawar", powerCall);
PDL_JSRegistrationComplete();
PDL_CallJS("ready", NULL, 0); // this is for enyo
atexit(SDL_Quit);
atexit(PDL_Quit);
SDL_Event Event;
bool paused = false;
while (1) {
bool gotEvent;
if (paused) {
SDL_WaitEvent(&Event);
gotEvent = true;
}
else {
gotEvent = SDL_PollEvent(&Event);
}
while (gotEvent) {
switch (Event.type) {
case SDL_ACTIVEEVENT:
if (Event.active.state == SDL_APPACTIVE) {
paused = !Event.active.gain;
}
break;
case SDL_QUIT:
// We exit anytime we get a request to quit the app
// all shutdown code is registered via atexit() so this is clean.
exit(0);
break;
// handle any other events interesting to your plugin here
default:
break;
}
gotEvent = SDL_PollEvent(&Event);
}
}
return 0;
}

Related

Understanding DirectoryWatcher

I've been trying to use and understand the DirectoryWatcher class from Microsoft's Cloud Mirror sample. It uses ReadDirectoryChangesW to monitor changes to a directory. I don't think it's reporting all changes, to be honest. In any event, I had a question about the key part of the code, which is as follows:
concurrency::task<void> DirectoryWatcher::ReadChangesAsync()
{
auto token = _cancellationTokenSource.get_token();
return concurrency::create_task([this, token]
{
while (true)
{
DWORD returned;
winrt::check_bool(ReadDirectoryChangesW(
_dir.get(),
_notify.get(),
c_bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_ATTRIBUTES,
&returned,
&_overlapped,
nullptr));
DWORD transferred;
if (GetOverlappedResultEx(_dir.get(), &_overlapped, &transferred, 1000, FALSE))
{
std::list<std::wstring> result;
FILE_NOTIFY_INFORMATION* next = _notify.get();
while (next != nullptr)
{
std::wstring fullPath(_path);
fullPath.append(L"\\");
fullPath.append(std::wstring_view(next->FileName, next->FileNameLength / sizeof(wchar_t)));
result.push_back(fullPath);
if (next->NextEntryOffset)
{
next = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<char*>(next) + next->NextEntryOffset);
}
else
{
next = nullptr;
}
}
_callback(result);
}
else if (GetLastError() != WAIT_TIMEOUT)
{
throw winrt::hresult_error(HRESULT_FROM_WIN32(GetLastError()));
}
else if (token.is_canceled())
{
wprintf(L"watcher cancel received\n");
concurrency::cancel_current_task();
return;
}
}
}, token);
}
After reviewing an answer to another question, here's what I don't understand about the code above: isn't the code potentially re-calling ReadDirectoryChangesW before the prior call has returned a result? Or is this code indeed correct? Thanks for any input.
Yes, I seem to have confirmed in my testing that there should be another while loop there around the call to GetOverlappedResultEx, similar to the sample code provided in that other answer. I think the notifications are firing properly with it.
Shouldn't there also be a call to CancelIo in there, too? Or is that not necessary for some reason?

alBufferData() sets AL_INVALID_OPERATION when using buffer ID obtained from alSourceUnqueueBuffers()

I am trying to stream audio data from disk using OpenAL's buffer queueing mechanism. I load and enqueue 4 buffers, start the source playing, and check in a regular intervals to refresh the queue. Everything looks like it's going splendidly, up until the first time I try to load data into a recycled buffer I got from alSourceUnqueueBuffers(). In this situation, alBufferData() always sets AL_INVALID_OPERATION, which according to the official v1.1 spec, it doesn't seem like it should be able to do.
I have searched extensively on Google and StackOverflow, and can't seem to find any reason why this would happen. The closest thing I found was someone with a possibly-related issue in an archived forum post, but details are few and responses are null. There was also this SO question with slightly different circumstances, but the only answer's suggestion does not help.
Possibly helpful: I know my context and device are configured correctly, because loading small wav files completely into a single buffer and playing them works fine. Through experimentation, I've also found that queueing 2 buffers, starting the source playing, and immediately loading and enqueueing the other two buffers throws no errors; it's only when I've unqueued a processed buffer that I run into trouble.
The relevant code:
static constexpr int MAX_BUFFER_COUNT = 4;
#define alCall(funcCall) {funcCall; SoundyOutport::CheckError(__FILE__, __LINE__, #funcCall) ? abort() : ((void)0); }
bool SoundyOutport::CheckError(const string &pFile, int pLine, const string &pfunc)
{
ALenum tErrCode = alGetError();
if(tErrCode != 0)
{
auto tMsg = alGetString(tErrCode);
Log::e(ro::TAG) << tMsg << " at " << pFile << "(" << pLine << "):\n"
<< "\tAL call " << pfunc << " failed." << end;
return true;
}
return false;
}
void SoundyOutport::EnqueueBuffer(const float* pData, int pFrames)
{
static int called = 0;
++called;
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
if(tState == AL_STATIC)
{
Stop();
// alCall(alSourcei(mSourceId, AL_BUFFER, NULL));
}
ALuint tBufId = AL_NONE;
int tQueuedBuffers = QueuedUpBuffers();
int tReady = ProcessedBuffers();
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
void* tConverted = convert(pData, pFrames);
// the fifth time through, we get AL_INVALID_OPERATION, and call abort()
alCall(alBufferData(tBufId, mFormat, tConverted, pFrames * mBitdepth/8, mSampleRate));
alCall(alSourceQueueBuffers(mSourceId, 1, &mBufferId));
if(mBitdepth == BITDEPTH_8)
{
delete (uint8_t*)tConverted;
}
else // if(mBitdepth == BITDEPTH_16)
{
delete (uint16_t*)tConverted;
}
}
void SoundyOutport::PlayBufferedStream()
{
if(!StreamingMode() || !QueuedUpBuffers())
{
Log::w(ro::TAG) << "Attempted to play an unbuffered stream" << end;
return;
}
alCall(alSourcei(mSourceId, AL_LOOPING, AL_FALSE)); // never loop streams
alCall(alSourcePlay(mSourceId));
}
int SoundyOutport::QueuedUpBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tCount));
return tCount;
}
int SoundyOutport::ProcessedBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_PROCESSED, &tCount));
return tCount;
}
void SoundyOutport::Stop()
{
if(Playing())
{
alCall(alSourceStop(mSourceId));
}
int tBuffers;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tBuffers));
if(tBuffers)
{
ALuint tDummy[tBuffers];
alCall(alSourceUnqueueBuffers(mSourceId, tBuffers, tDummy));
}
alCall(alSourcei(mSourceId, AL_BUFFER, AL_NONE));
}
bool SoundyOutport::Playing()
{
ALint tPlaying;
alCall(alGetSourcei(mSourceId, AL_SOURCE_STATE, &tPlaying));
return tPlaying == AL_PLAYING;
}
bool SoundyOutport::StreamingMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STREAMING;
}
bool SoundyOutport::StaticMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STATIC;
}
And here's an annotated screen cap of what I see in my debugger when I hit the error:
I've tried a bunch of little tweaks and variations, and the result is always the same. I've wasted too many days trying to fix this. Please help :)
This error occurs when you trying to fill buffer with data, when the buffer is still queued to the source.
Also this code is wrong.
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
You can fill buffer with data only if it unqueued from source. But your first if block gets tBufId that queued to the source. Rewrite code like so
if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}

Monitor process exceptions via Debug API

Any help to start using sample code find at C++/CLI Win32 debugger library for x86 to monitor process exceptions.
Some code I made is :
using System;
using DebugLibrary;
namespace DebugTeste01
{
class Program
{
static void Main(string[] args)
{
DebugUtil.DebugActiveProcess(4932);
DebugEvent de = new DebugEvent();
ThreadContext tc = new ThreadContext();
LDTEntry ldte = new LDTEntry();
do
{
debug_evt = DebugUtil.WaitForDebugEvent(0xffffffff);
de = (DebugEvent)debug_evt;
Process proc = Process.GetProcessById(de.processId);
object meminfo = DebugUtil.GetMemoryInfo(proc.Handle);
//...
object modinf = DebugUtil.GetModuleInfo(proc.Handle);
//...
switch (debug_evt.GetType().ToString())
{
case "DebugLibrary.DebugEvent_CreateProcess":
{
DebugEvent_CreateProcess decp = (DebugEvent_CreateProcess)debug_evt;
//some action, logging, etc.
}
break;
case "DebugLibrary.DebugEvent_LoadDll":
{
DebugEvent_LoadDll dect = (DebugEvent_LoadDll)debug_evt;
//some action, logging, etc.
}
break;
case "DebugLibrary.DebugEvent_CreateThread":
{
DebugEvent_CreateThread dect = (DebugEvent_CreateThread)debug_evt;
//some action, logging, etc.
}
break;
case "DebugLibrary.DebugEvent_ExitThread":
{
DebugEvent_ExitThread dect = (DebugEvent_ExitThread)debug_evt;
//some action, logging, etc.
}
break;
case "DebugLibrary.DebugEvent_Exception":
{
DebugEvent_Exception dect = (DebugEvent_Exception)debug_evt;
ExceptionRecord exbp = dect.exceptionRecord;
switch (exbp.GetType().ToString())
{
case "Breakpoint":
{
//some action, logging, etc.
exbp = null;
}
break;
case "AccessViolation":
{
//some action, logging, etc.
exbp = null;
}
break;
//more case
}
}
break;
default:
{
//some action, logging, etc.
debug_evt = null;
}
break;
}
try
{
DebugUtil.ContinueDebugEvent(de.processId, de.threadId, false);
}
catch
{
break;
}
}
while ( true );
}
}
}
[EDIT] 03/14/2012
Good article: Using the Windows Debugging API
[EDIT] 03/14/2012
Improvements in implementation.
Now it has an initial skeleton construction for a final application.
Seems to me you are after resources on debugger writing for understanding, in which case, your best place to start is MSDN, this gives the basics of what should be handled how. from there its really up to your application and environment how you handle the exceptions.
As a comment on your actual code, avoid hardcoding to a PID, rather use the process name.

Debugging panics in Symbian OS using Carbide.c++

Is there a way to drop into the debugger when any panic occurs like if there were a breakpoint?
I'm using Carbide.c++ 2.3.0. I know about the Debug Configurations > x86 Exceptions, but it covers only a small fraction of what can actually happen in a real application. For instance, it does not trap user panics, or ALLOC panics when application exits with memory leaks.
If you are using the emulator, you can debug panics by enabling 'just-in-time debugging. This is done by adding the following line to epoc32\data\epoc.ini:
JustInTime debug
For more details, see the epoc.ini reference in the SDK documentation.
To the best of my knowledge it can't be done.
What I've done is use simple function tracing logic so when a panic happens I have a stack trace at the point of the panic in my the panic handling code (which I log out). This works well except for the fact that you have to remember to add your macro's at the beginning of every function.
e.g.
#ifndef NDEBUG
class __FTrace
{
__FTrace(const char* function)
{
TraceManager::GetInstance().EnterFunction(function);
}
~__FTrace()
{
TraceManager::GetInstance().LeaveFunction(function);
}
};
#define FTRACE() __FTrace(__PRETTY_FUNCTION__)
#else
#define FTRACE()
#endif
void Func()
{
FTRACE();
...
}
For ALLOC's, I've had a lot of success with the Hook Logger under the emulator. It's a real pain to setup and use but it will make it real easy to track down ALLOC memory leaks.
UPDATE: As requested, here is what my panic handling code looks like. Note that my application has to run in the background all the time, so it's setup to restart the app when something bad happens. Also this code works for 3rd Edition SDK's, I haven't tried it on later versions of the SDK's.
The point is to run the main application in another thread and then wait for it to exit. Then check to see why the thread exits, it the thread as exited for unknown reasons, log stuff like my own stack trace and restart the application.
TInt StartMainThread(TAny*)
{
FTRACE();
__LOGSTR_TOFILE("Main Thread Start");
TInt result(KErrNone);
TRAPD(err, result = EikStart::RunApplication(NewApplication));
if(KErrNone != err || KErrNone != result )
{
__LOGSTR_TOFILE("EikStart::RunApplication error: trap(%d), %d", err, result);
}
__LOGSTR_TOFILE("Main Thread End");
return result;
}
const TInt KMainThreadToLiveInSeconds = 10;
} // namespace *unnamed*
LOCAL_C CApaApplication* NewApplication()
{
FTRACE();
return new CMainApplication;
}
GLDEF_C TInt E32Main()
{
#ifdef NDEBUG
__LOGSTR_TOFILE("Application Start (release)");
#else
__LOGSTR_TOFILE("Application Start (debug)");
#endif
#ifndef NO_TRACING
__TraceManager::NewL();
#endif // !NO_TRACING
RHeap& heap(User::Heap());
TInt heapsize=heap.MaxLength();
TInt exitReason(KErrNone);
TTime timeToLive;
timeToLive.UniversalTime();
timeToLive += TTimeIntervalSeconds(KMainThreadToLiveInSeconds);
LManagedHandle<RThread> mainThread;
TInt err = mainThread->Create(_L("Main Thread"), StartMainThread, KDefaultStackSize, KMinHeapSize, heapsize, NULL);
if (KErrNone != err)
{
__LOGSTR_TOFILE("MainThread failed : %d", err);
return err;
}
mainThread->SetPriority(EPriorityNormal);
TRequestStatus status;
mainThread->Logon(status);
mainThread->Resume();
User::WaitForRequest(status);
exitReason = mainThread->ExitReason();
TExitCategoryName category(mainThread->ExitCategory());
switch(mainThread->ExitType())
{
case EExitKill:
__LOGSTR_TOFILE("ExitKill : (%S) : %d", &category, exitReason);
break;
case EExitTerminate:
__LOGSTR_TOFILE("ExitTerminate : (%S) : %d", &category, exitReason);
break;
case EExitPanic:
__LOGSTR_TOFILE("ExitPanic : (%S) : %d", &category, exitReason);
break;
default:
__LOGSTR_TOFILE("ExitUnknown : (%S) : %d", &category, exitReason);
break;
}
#ifndef NO_TRACING
__TraceManager::GetInstance().LogStackTrace();
#endif // NO_TRACING
if( KErrNone != status.Int() )
{
TTime now;
now.UniversalTime();
if (timeToLive > now)
{
TTimeIntervalMicroSeconds diff = timeToLive.MicroSecondsFrom(now);
__LOGSTR_TOFILE("Exiting due to TTL : (%Lu)", diff.Int64());
}
else
{
RProcess current;
RProcess restart;
err = restart.Create(current.FileName(), _L(""));
if( KErrNone == err )
{
__LOGSTR_TOFILE("Restarting...");
restart.Resume();
return KErrNone;
}
else
{
__LOGSTR_TOFILE("Failed to start app: %d", err);
}
}
}
__LOGSTR_TOFILE("Application End");
return exitReason;
}

Displaying progressbar using threading in win 32 applicaition!

In my application I have a simple module were I will read files for some process that will take
few seconds..so I thought of displaying a progress bar(using worker thread) while the files are in progress.I have created a thread (code shown below) and also I designed a dialog window with progress control.I used the function MyThreadFunction below to display the progressbar but it just shows only one time and disappears,I am not sure how to make it work.I tried my best inspite of the fact that I am new to threading.
reading files
void ReadMyFiles()
{
for(int i = 0; i < fileCount ; fileCount++)
{
CWinThread* myThread = AfxBeginThread((AFX_THREADPROC)MyThreadFunction,NULL);
tempState = *(checkState + index);
if(tempCheckState == NOCHECKBOX)
{
//my operations
}
else//CHECKED or UNCHECKED
{
//myoperation
}
myThread->PostThreadMessage(WM_QUIT,NULL,NULL);
}
}
thread functions
UINT MyThreadFunction(LPARAM lparam)
{
HWND dialogWnd = CreateWindowEx(0,WC_DIALOG,L"Proccessing...",WS_OVERLAPPEDWINDOW|WS_VISIBLE,
600,300,280,120,NULL,NULL,NULL,NULL);
HWND pBarWnd = CreateWindowEx(NULL,PROGRESS_CLASS,NULL,WS_CHILD|WS_VISIBLE|PBS_MARQUEE,40,20,200,20,
dialogWnd,(HMENU)IDD_PROGRESS,NULL,NULL);
MSG msg;
PostMessage( pBarWnd, PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
PostMessage(pBarWnd,PBM_SETPOS,0,0);
while(PeekMessage(&msg,NULL,NULL,NULL,PM_NOREMOVE))
{
if(msg.message == WM_QUIT)
{
DestroyWindow(dialogWnd);
return 1;
}
AfxGetThread()->PumpMessage();
Sleep(40);
}
return 1;
}
Do you really want to create a new thread and a progress bar for each individual file? Create the thread outside of the for() loop.
But this is not the right way to do it, your main UI is still dead as a doornail. Windows will turn your main window in a ghost with "Not Responding" in the title bar after a couple of seconds. You want to use a worker thread to do the file manipulation and the main thread to display the progress bar using a dialog that can only be closed when the worker uses PostMessage() to indicate completion.

Resources