Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
BlackBerry Development Advisor
Posts: 683
Registered: ‎11-29-2011
My Device: PRIV
My Carrier: Rogers

Re: Open playbook camera in Qt project

the viewfinder is a window.  you can set it's zorder.  see the NativeCamera sample.

 

In your code a few posts above, I saw you retrieve the group name from that window, but then you didn't pass it to the camera before starting the viewfinder.  When the camera service starts the viewfinder, it looks for CAMERA_IMGPROP_WIN_GROUPID and then does a screen_join_window_group().  Your top-level event loop should be able to report the screen_window_t after this join is detected.  If you are incapable of doing this because your screen event loop is hidden away inside Qt, then you will need to modify Qt to allow for a signal to be emitted when this event happens.

Contributor
Posts: 34
Registered: ‎10-08-2012
My Device: developer
My Carrier: ??

Re: Open playbook camera in Qt project

[ Edited ]

could you be a little bit more specific about where in the native sample?

because I can't find it.(possibly because I don't know what to look for)

EDIT: ok I realy need to learn how to look for stuff. found where the z of the viewfinder is set.

 

and as far as i know i give the groupid to the viewfinder.

or is getting the group using this

screen_get_window_property_cv((screen_window_t)this->topLevelWidget()->winId(), SCREEN_PROPERTY_GROUP, 199, test);

 and then giving it to the viewfinder like this:

amera_set_photovf_property(handle, CAMERA_IMGPROP_WIN_GROUPID, test);

 not enough to let the viewfinder know what group it should be added to?

Contributor
Posts: 34
Registered: ‎10-08-2012
My Device: developer
My Carrier: ??

Re: Open playbook camera in Qt project

for some reason there is still something going wrong.

i went back to the code i posted somewhere in the begining(modification of native camera) and added the changes sudgested.

the problem is that even though I put the viewfinder higher then the Qt window and the black nativescreen i still only see a black schreen when i start everything.

and to help you guys here is the code I have now:

#include <assert.h>
#include <bps/bps.h>
#include <bps/event.h>
#include <bps/navigator.h>
#include <bps/screen.h>
#include <fcntl.h>
#include <screen/screen.h>
#include <camera/camera_api.h>
#include <bps/soundplayer.h>
#include "camerastart.h"

typedef enum {
    STATE_STARTUP = 0,
    STATE_VIEWFINDER,
    STATE_TAKINGPHOTO
} state_t;


static bool shutdown = false;
static screen_context_t screen_ctx;
static screen_window_t vf_win = NULL;
static const char *vf_group;
static state_t state = STATE_STARTUP;
static camera_handle_t handle = CAMERA_HANDLE_INVALID;
static bool shouldmirror = false;
static bool touch = false;
static int photo_done_domain = -1;
static int main_bps_chid = -1;

cameraStart::cameraStart()
{
}

void cameraStart::start(const char *group)
{
    vf_group = group;

    const int usage = SCREEN_USAGE_NATIVE;

        screen_window_t screen_win;
        screen_buffer_t screen_buf = NULL;
        int rect[4] = { 0, 0, 0, 0 };

        // create an application window which will just act as a background
        screen_create_context(&screen_ctx, 0);
        screen_create_window_type(&screen_win, screen_ctx, SCREEN_CHILD_WINDOW);
        //screen_create_window(&screen_win, screen_ctx);
        //screen_create_window_group(screen_win, vf_group);
        screen_join_window_group(screen_win, vf_group);
        int z = 1;
        screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &z);
        screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
        screen_create_window_buffers(screen_win, 1);
        screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf);
        screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);

        // fill the window with black
        int attribs[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
        screen_fill(screen_ctx, screen_buf, attribs);
        screen_post_window(screen_win, screen_buf, 1, rect, 0);

        // Signal bps library that navigator and screen events will be requested
        bps_initialize();
        main_bps_chid = bps_channel_get_active();
        screen_request_events(screen_ctx);
        navigator_request_events(0);

        // create a custom BPS event that we can use in to let our main thread know
        // that photo-taking is finished
        photo_done_domain = bps_register_domain();

        // open camera and configure viewfinder
        if (init_camera(CAMERA_UNIT_REAR) == EOK) {
            // our main loop just runs a state machine and handles input
            while (!shutdown) {
                run_state_machine();
                // Handle user input
                handle_event();
            }

            if (state == STATE_TAKINGPHOTO) {
                // wait for picture-taking to finish? TBD
                state = STATE_VIEWFINDER;
            }
            if (state == STATE_VIEWFINDER) {
                // clean up camera
                camera_stop_photo_viewfinder(handle);
                camera_close(handle);
            }
        }

        // Clean up
        screen_stop_events(screen_ctx);
        bps_shutdown();
        screen_destroy_window(screen_win);
        screen_destroy_context(screen_ctx);
}

void cameraStart::handle_screen_event(bps_event_t *event)
{
    int screen_val;
    screen_event_t screen_event = screen_event_get_event(event);
    screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val);

    switch (screen_val) {
    case SCREEN_EVENT_MTOUCH_TOUCH:
        touch = true;
        break;
    case SCREEN_EVENT_MTOUCH_MOVE:
        break;
    case SCREEN_EVENT_MTOUCH_RELEASE:
        break;
    case SCREEN_EVENT_CREATE:
        if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void **)&vf_win) == -1) {
            perror("screen_get_event_property_pv(SCREEN_PROPERTY_WINDOW)");
        } else {
            // mirror viewfinder if this is the front-facing camera
            int i = (shouldmirror?1:0);
            screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_MIRROR, &i);
            // place viewfinder in front of the black application background window
            // child window z-orders are relative to their parent, not absolute.
            i = 4;
            screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_ZORDER, &i);
            // make viewfinder window visible
            i = 1;
            screen_set_window_property_iv(vf_win, SCREEN_PROPERTY_VISIBLE, &i);
            screen_flush_context(screen_ctx, 0);
            // we should now have a visible viewfinder
            touch = false;
            state = STATE_VIEWFINDER;
        }
        break;
    default:
        break;
    }
}

void cameraStart::handle_navigator_event(bps_event_t *event) {
    switch (bps_event_get_code(event)) {
    case NAVIGATOR_SWIPE_DOWN:
        break;
    case NAVIGATOR_EXIT:
        shutdown = true;
        break;
    default:
        break;
    }
}

void cameraStart::handle_photo_done_event(bps_event_t *event) {
    // re-arm the viewfinder state
    touch = false;
    state = STATE_VIEWFINDER;
}


void cameraStart::handle_event()
{
    int rc, domain;

    bps_event_t *event = NULL;
    rc = bps_get_event(&event, -1);
    assert(rc == BPS_SUCCESS);
    if (event) {
        domain = bps_event_get_domain(event);
        if (domain == navigator_get_domain()) {
            handle_navigator_event(event);
        } else if (domain == screen_get_domain()) {
            handle_screen_event(event);
        } else if (domain == photo_done_domain) {
            handle_photo_done_event(event);
        }
    }
}


void cameraStart::shutter_callback(camera_handle_t handle, void* arg)
{
    // THE CAMERA SERVICE DOES NOT PLAY SOUNDS WHEN PICTURES ARE TAKEN OR
    // VIDEOS ARE RECORDED. IT IS THE APP DEVELOPER'S RESPONSIBILITY TO
    // PLAY AN AUDIBLE SHUTTER SOUND WHEN A PICTURE IS TAKEN AND WHEN VIDEO
    // RECORDING STARTS AND STOPS. NOTE THAT WHILE YOU MAY CHOOSE TO MUTE
    // SUCH SOUNDS, YOU MUST ENSURE THAT YOUR APP ADHERES TO ALL LOCAL LAWS
    // OF REGIONS WHERE IT IS DISTRIBUTED. FOR EXAMPLE, IT IS ILLEGAL TO
    // MUTE OR MODIFY THE SHUTTER SOUND OF A CAMERA APPLICATION IN JAPAN OR
    // KOREA.
    // TBD:
    // RIM will be providing clarification of this policy as part of the
    // NDK developer agreement and App World guidelines. A link will
    // be provided when the policy is publicly available.
    fprintf(stderr, "sound\n");
    soundplayer_play_sound("event_camera_shutter");
}


void cameraStart::still_callback(camera_handle_t handle,
               camera_buffer_t* buf,
               void* arg)
{
    fprintf(stderr, "start callback\n");
    if (buf->frametype == CAMERA_FRAMETYPE_JPEG) {
        fprintf(stderr, "frame is JPEG frame\n");
        int fd;
        char filename[CAMERA_ROLL_NAMELEN];
        if (camera_roll_open_photo(handle,
                                   &fd,
                                   filename,
                                   sizeof(filename),
                                   CAMERA_ROLL_PHOTO_FMT_JPG) == CAMERA_EOK) {
            fprintf(stderr, "photo open\n");
            int index = 0;
            while(index < (int)buf->framedesc.jpeg.bufsize) {
                int rc = write(fd, &buf->framebuf[index], buf->framedesc.jpeg.bufsize-index);
                if (rc > 0) {
                    index += rc;
                } else if (rc == -1) {
                    if ((errno == EAGAIN) || (errno == EINTR)) continue;
                    perror("write");
                    break;
                }
            }
            close(fd);
        }
    }
    fprintf(stderr, "after if");
    // picture-taking is done, so wake up the main thread again via bps.
    // note that we are using the void* arg here as the bps channel to deliver
    // the event on. this is just to demonstrate data passing between
    // camera_take_photo() and the various callback functions.
    bps_event_t* photo_done_event;
    bps_event_create(&photo_done_event, photo_done_domain, 0, NULL, NULL);
    bps_channel_push_event((int)arg, photo_done_event);
}


void cameraStart::run_state_machine()
{
    camera_error_t err;
    // this simple state machine just runs us through starting a viewfinder and taking pictures
    switch(state) {
    case STATE_STARTUP:
        // waiting for viewfinder...
        break;
    case STATE_VIEWFINDER:
        // viewfinder is visible.
        // if the user touches the screen anywhere, take a picture.
        // note, we are passing main_bps_chid as the void* arg which will then
        // be delivered to all callbacks. main_bps_chid is already a global variable,
        // so this isn't necessary, but is just done here to illustrate the convention.changes
        if (touch) {
            touch = false;
            fprintf(stderr, "try taking photo\n");
            err = camera_take_photo(handle,
                                    (void(*)(camera_handle_t,void*))&cameraStart::shutter_callback,
                                    NULL,
                                    NULL,
                                    (void(*)(camera_handle_t, camera_buffer_t*,void*))&cameraStart::still_callback,
                                    (void*)main_bps_chid,
                                    false);
            if (err != CAMERA_EOK) {
            } else {
                state = STATE_TAKINGPHOTO;
            }
        }
        break;
    default:
        break;
    }
}

int cameraStart::init_camera(camera_unit_t unit)
{
    camera_error_t err;
    // open the specified camera
    fprintf(stderr, "initiate camera\n");
    err = camera_open(unit,
                      CAMERA_MODE_RW | CAMERA_MODE_ROLL,
                      &handle);
    fprintf(stderr, "camera open\n");
    if (err != CAMERA_EOK) {
        fprintf(stderr, "opening camera failed\n");
        return err;
    }
    err = camera_set_photovf_property(handle,
                                      CAMERA_IMGPROP_WIN_GROUPID, vf_group,
                                      CAMERA_IMGPROP_WIN_ID, "my_viewfinder");
    fprintf(stderr, "settings are set\n");
    if (err != CAMERA_EOK) {
        fprintf(stderr, "failure setting settings\n");
    } else {
        fprintf(stderr, "viewfinder starting\n");
        err = camera_start_photo_viewfinder(handle,
                                            NULL,
                                            NULL,
                                            NULL);
        fprintf(stderr, "done starting viewfinder\n");
        if (err != CAMERA_EOK) {
            fprintf(stderr, "error starting viewfinder\n" + err);
        } else {
            // successfully started viewfinder
            // if it's a front-facing camera, we should mirror the viewfinder once
            // we receive it.
            if (unit == CAMERA_UNIT_FRONT) {
                shouldmirror = true;
            }
            return 0;
        }
    }
    // clean up on error
    camera_close(handle);
    handle = CAMERA_HANDLE_INVALID;
    return err;
}

 

BlackBerry Development Advisor
Posts: 683
Registered: ‎11-29-2011
My Device: PRIV
My Carrier: Rogers

Re: Open playbook camera in Qt project


somedeveloperguy wrote:

and as far as i know i give the groupid to the viewfinder.




ah nevermind then.. I misread your previous post.. did not realize you were setting 2 properties on the same line due to test wrapping.

BlackBerry Development Advisor
Posts: 683
Registered: ‎11-29-2011
My Device: PRIV
My Carrier: Rogers

Re: Open playbook camera in Qt project

Hmm.. you're trying to attach the viewfinder to a child window.  You will have to set CAMERA_IMGPROP_ISEMBEDDED = 1, to get this to work -- this creates the viewfinder as an "embedded" window (eg. a child of a child).  I have never done this before, so you'll be trailblazing the solution here.

 

are you ever hitting this code?

    case SCREEN_EVENT_CREATE:
Trusted Contributor
Posts: 160
Registered: ‎09-13-2012
My Device: 9900
My Carrier: vodafone

Re: Open playbook camera in Qt project

are you still using this->topLevelWidget()->windId() to get the group? I just use window.winId() from outside my window to get the goup and just winId() inside my window class.

 

Don't know if it makes a difference but it might. Also try getting all other screens and setting them to -1 for z-order.

 

Another issue I never got round was 3 windows but that might have been for screen events, I ended up having one native window and one qt window and the qt window showed different things depending on what was clicked.

Contributor
Posts: 34
Registered: ‎10-08-2012
My Device: developer
My Carrier: ??

Re: Open playbook camera in Qt project

[ Edited ]

I tried to add CAMERA_IMGPROP_ISEMBEDDED = 1 to my code(in the set_photovf_properties method) but for some reason it is not known by my compiler.(its not in the camera_api.h file as well. is there a new version of the SDK?)

EDIT: reïnstalling the SDK indeed gave me the ISEMBEDDED property but setting it to 1 has no effect at the moment

 

and I think the problem is indeed that it does not execute the code inside

case SCREEN_EVENT_CREATE:

 

only problem is that I don't know where that event is (supposed to be) created.

is there a sollution for this?

BlackBerry Development Advisor
Posts: 683
Registered: ‎11-29-2011
My Device: PRIV
My Carrier: Rogers

Re: Open playbook camera in Qt project

If you are integrated with Qt, then my assumption is that either Qt is eating that event (which is expected, because Qt it the screen event consumer for your app), or that the viewfinder window has joined the wrong group.

 

If you attach a preview callback when starting the viewfinder, does it ever get triggered?

Contributor
Posts: 34
Registered: ‎10-08-2012
My Device: developer
My Carrier: ??

Re: Open playbook camera in Qt project

I have no idea what you mean by a preview callback. could you explain that so I can test it?

 

and what I have learned while testing some more is that it does not trigger the mentioned screenevent, but it gives of 2 unknown screenevents(that go to the case defauld).

but when the backgroundscreen is loaded i get every screenevent that happens(touch, move and relaese) in that method.

BlackBerry Development Advisor
Posts: 683
Registered: ‎11-29-2011
My Device: PRIV
My Carrier: Rogers

Re: Open playbook camera in Qt project