The DVB TV application, can probably be used as a generic TV
application, or even merged with MediaPlayer and CDPlayer later. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20709 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
#include <ParameterWeb.h>
|
||||
#include <TimeSource.h>
|
||||
|
||||
#include "Controller.h"
|
||||
#include "DeviceRoster.h"
|
||||
#include "VideoView.h"
|
||||
#include "VideoNode.h"
|
||||
|
||||
extern bool gOverlayDisabled;
|
||||
|
||||
status_t MediaRoster_Disconnect(const media_output &output, const media_input &input);
|
||||
|
||||
|
||||
|
||||
media_node dvb_node;
|
||||
media_node audio_mixer_node;
|
||||
media_node video_window_node;
|
||||
media_node time_node;
|
||||
|
||||
media_input audio_input;
|
||||
media_output audio_output;
|
||||
media_input video_input;
|
||||
media_output video_output;
|
||||
|
||||
BMediaRoster *gMediaRoster;
|
||||
|
||||
void
|
||||
HandleError(const char *text, status_t err)
|
||||
{
|
||||
if (err != B_OK) {
|
||||
printf("%s. error 0x%08x (%s)\n",text, (int)err, strerror(err));
|
||||
fflush(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Controller::Controller()
|
||||
: fCurrentInterface(-1)
|
||||
, fCurrentChannel(-1)
|
||||
, fVideoView(NULL)
|
||||
, fVideoNode(NULL)
|
||||
, fWeb(NULL)
|
||||
, fChannelParam(NULL)
|
||||
, fConnected(false)
|
||||
, fInput()
|
||||
, fOutput()
|
||||
{
|
||||
gMediaRoster = BMediaRoster::Roster();
|
||||
}
|
||||
|
||||
|
||||
Controller::~Controller()
|
||||
{
|
||||
delete fWeb;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Controller::SetVideoView(VideoView *view)
|
||||
{
|
||||
fVideoView = view;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Controller::SetVideoNode(VideoNode *node)
|
||||
{
|
||||
fVideoNode = node;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Controller::DisconnectInterface()
|
||||
{
|
||||
DisconnectNodes();
|
||||
fCurrentInterface = -1;
|
||||
fCurrentChannel = -1;
|
||||
delete fWeb;
|
||||
fWeb = 0;
|
||||
fChannelParam = 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Controller::ConnectInterface(int i)
|
||||
{
|
||||
if (i < 0) {
|
||||
printf("Controller::ConnectInterface: wrong index\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
if (fCurrentInterface != -1) {
|
||||
printf("Controller::ConnectInterface: already connected\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
BParameterWeb *web;
|
||||
status_t err;
|
||||
|
||||
err = gDeviceRoster->MediaRoster()->GetParameterWebFor(gDeviceRoster->DeviceNode(i), &web);
|
||||
if (err != B_OK) {
|
||||
printf("Controller::ConnectInterface: can't get parameter web\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
delete fWeb;
|
||||
fWeb = web;
|
||||
fCurrentInterface = i;
|
||||
|
||||
// XXX we may need to monitor for parameter web changes
|
||||
// and reassing fWeb and fChannelParam on demand.
|
||||
|
||||
// find the channel control and assign it to fChannelParam
|
||||
fChannelParam = NULL;
|
||||
int count = fWeb->CountParameters();
|
||||
for (int i = 0; i < count; i++) {
|
||||
BParameter *parameter = fWeb->ParameterAt(i);
|
||||
|
||||
printf("parameter %d\n", i);
|
||||
printf(" name '%s'\n", parameter->Name());
|
||||
printf(" kind '%s'\n", parameter->Kind());
|
||||
printf(" unit '%s'\n", parameter->Unit());
|
||||
printf(" flags 0x%08lx\n", parameter->Flags());
|
||||
|
||||
// XXX TODO: matching on Name is weak
|
||||
if (strcmp(parameter->Name(), "Channel") == 0 || strcmp(parameter->Kind(), B_TUNER_CHANNEL) == 0) {
|
||||
fChannelParam = dynamic_cast<BDiscreteParameter *>(parameter);
|
||||
if (fChannelParam)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!fChannelParam) {
|
||||
printf("Controller::ConnectInterface: can't find channel parameter control\n");
|
||||
fCurrentChannel = -1;
|
||||
} else {
|
||||
if (fChannelParam->CountItems() == 0) {
|
||||
fCurrentChannel = -1;
|
||||
printf("Controller::ConnectInterface: channel control has 0 items\n");
|
||||
} else {
|
||||
int32 index;
|
||||
size_t size;
|
||||
status_t err;
|
||||
bigtime_t when;
|
||||
size = sizeof(index);
|
||||
err = fChannelParam->GetValue(&index, &size, &when);
|
||||
if (err == B_OK && size == sizeof(index)) {
|
||||
fCurrentChannel = index;
|
||||
printf("Controller::ConnectInterface: selected channel is %d\n", fCurrentChannel);
|
||||
} else {
|
||||
fCurrentChannel = -1;
|
||||
printf("Controller::ConnectInterface: can't get channel control value\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConnectNodes();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Controller::IsInterfaceAvailable(int i)
|
||||
{
|
||||
return gDeviceRoster->IsRawAudioOutputFree(i) && gDeviceRoster->IsRawVideoOutputFree(i);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Controller::CurrentInterface()
|
||||
{
|
||||
return fCurrentInterface;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Controller::CurrentChannel()
|
||||
{
|
||||
return fCurrentChannel;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Controller::SelectChannel(int i)
|
||||
{
|
||||
if (!fChannelParam)
|
||||
return B_ERROR;
|
||||
|
||||
int32 index;
|
||||
status_t err;
|
||||
index = i;
|
||||
err = fChannelParam->SetValue(&index, sizeof(index), 0);
|
||||
if (err != B_OK) {
|
||||
printf("Controller::SelectChannel %d failed\n", i);
|
||||
return err;
|
||||
}
|
||||
|
||||
fCurrentChannel = i;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Controller::ChannelCount()
|
||||
{
|
||||
if (fCurrentInterface == -1)
|
||||
return 0;
|
||||
|
||||
if (!fChannelParam)
|
||||
return 0;
|
||||
|
||||
return fChannelParam->CountItems();
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
Controller::ChannelName(int i)
|
||||
{
|
||||
if (fCurrentInterface == -1)
|
||||
return NULL;
|
||||
|
||||
if (!fChannelParam)
|
||||
return NULL;
|
||||
|
||||
return fChannelParam->ItemNameAt(i);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Controller::VolumeUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Controller::VolumeDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Controller::ConnectNodes()
|
||||
{
|
||||
status_t err;
|
||||
|
||||
// dvb_node = gDeviceRoster->DeviceNode(fCurrentInterface);
|
||||
|
||||
err = gMediaRoster->GetNodeFor(gDeviceRoster->DeviceNode(fCurrentInterface).node, &dvb_node);
|
||||
HandleError("GetNodeFor failed", err);
|
||||
|
||||
video_window_node = fVideoNode->Node();
|
||||
|
||||
err = gMediaRoster->GetAudioMixer(&audio_mixer_node);
|
||||
HandleError("GetAudioMixer failed", err);
|
||||
|
||||
media_input input;
|
||||
media_output output;
|
||||
media_format fmt;
|
||||
int32 count;
|
||||
|
||||
// Connect audio
|
||||
|
||||
err = gMediaRoster->GetFreeOutputsFor(dvb_node, &output, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||
HandleError("Can't find free audio output", err);
|
||||
if (count < 1)
|
||||
HandleError("No free audio output", -1);
|
||||
|
||||
err = gMediaRoster->GetFreeInputsFor(audio_mixer_node, &input, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||
HandleError("Can't find free audio input", err);
|
||||
if (count < 1)
|
||||
HandleError("No free audio input", -1);
|
||||
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
err = gMediaRoster->Connect(output.source, input.destination, &fmt, &audio_output, &audio_input);
|
||||
HandleError("Can't connect audio", err);
|
||||
|
||||
// Connect video
|
||||
|
||||
err = gMediaRoster->GetFreeOutputsFor(dvb_node, &output, 1, &count, B_MEDIA_RAW_VIDEO);
|
||||
HandleError("Can't find free video output", err);
|
||||
if (count < 1)
|
||||
HandleError("No free video output", -1);
|
||||
|
||||
err = gMediaRoster->GetFreeInputsFor(video_window_node, &input, 1, &count, B_MEDIA_RAW_VIDEO);
|
||||
HandleError("Can't find free video input", err);
|
||||
if (count < 1)
|
||||
HandleError("No free video input", -1);
|
||||
|
||||
color_space cspaces_overlay[] = { B_YCbCr422, B_RGB32, B_NO_COLOR_SPACE };
|
||||
color_space cspaces_bitmap[] = { B_RGB32, B_NO_COLOR_SPACE };
|
||||
|
||||
if (gOverlayDisabled) {
|
||||
err = B_ERROR;
|
||||
} else {
|
||||
fVideoNode->SetOverlayEnabled(true);
|
||||
for (int i = 0; cspaces_overlay[i] != B_NO_COLOR_SPACE; i++) {
|
||||
printf("trying connect with colorspace 0x%08x\n", cspaces_overlay[i]);
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.type = B_MEDIA_RAW_VIDEO;
|
||||
fmt.u.raw_video.display.format = cspaces_overlay[i];
|
||||
err = gMediaRoster->Connect(output.source, input.destination, &fmt, &video_output, &video_input);
|
||||
if (err == B_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
fVideoNode->SetOverlayEnabled(false);
|
||||
for (int i = 0; cspaces_bitmap[i] != B_NO_COLOR_SPACE; i++) {
|
||||
printf("trying connect with colorspace 0x%08x\n", cspaces_bitmap[i]);
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.type = B_MEDIA_RAW_VIDEO;
|
||||
fmt.u.raw_video.display.format = cspaces_bitmap[i];
|
||||
err = gMediaRoster->Connect(output.source, input.destination, &fmt, &video_output, &video_input);
|
||||
if (err == B_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
HandleError("Can't connect video", err);
|
||||
|
||||
// set time sources
|
||||
|
||||
err = gMediaRoster->GetTimeSource(&time_node);
|
||||
HandleError("Can't get time source", err);
|
||||
|
||||
BTimeSource *ts = gMediaRoster->MakeTimeSourceFor(time_node);
|
||||
|
||||
err = gMediaRoster->SetTimeSourceFor(dvb_node.node, time_node.node);
|
||||
HandleError("Can't set dvb time source", err);
|
||||
|
||||
err = gMediaRoster->SetTimeSourceFor(audio_mixer_node.node, time_node.node);
|
||||
HandleError("Can't set audio mixer time source", err);
|
||||
|
||||
err = gMediaRoster->SetTimeSourceFor(video_window_node.node, time_node.node);
|
||||
HandleError("Can't set video window time source", err);
|
||||
|
||||
// Add a delay of (2 video frames) to the buffers send by the DVB node,
|
||||
// because as a capture device in B_RECORDING run mode it's supposed to
|
||||
// deliver buffers that were captured in the past (and does so).
|
||||
// It is important that the audio buffer size used by the connection with
|
||||
// the DVB node is smaller than this, optimum is the same length as one
|
||||
// video frame (40 ms). However, this is not yet guaranteed.
|
||||
err = gMediaRoster->SetProducerRunModeDelay(dvb_node, 80000);
|
||||
HandleError("Can't set DVB producer delay", err);
|
||||
|
||||
bigtime_t start_time = ts->Now() + 50000;
|
||||
|
||||
ts->Release();
|
||||
|
||||
// start nodes
|
||||
|
||||
err = gMediaRoster->StartNode(dvb_node, start_time);
|
||||
HandleError("Can't start dvb node", err);
|
||||
|
||||
err = gMediaRoster->StartNode(audio_mixer_node, start_time);
|
||||
HandleError("Can't start audio mixer node", err);
|
||||
|
||||
err = gMediaRoster->StartNode(video_window_node, start_time);
|
||||
HandleError("Can't start video window node", err);
|
||||
|
||||
printf("running...\n");
|
||||
|
||||
fConnected = true;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Controller::DisconnectNodes()
|
||||
{
|
||||
printf("stopping...\n");
|
||||
|
||||
if (!fConnected)
|
||||
return B_OK;
|
||||
|
||||
status_t err;
|
||||
|
||||
// stop nodes
|
||||
|
||||
err = gMediaRoster->StopNode(dvb_node, 0, true);
|
||||
HandleError("Can't stop dvb node", err);
|
||||
|
||||
err = gMediaRoster->StopNode(audio_mixer_node, 0, true);
|
||||
HandleError("Can't stop audio mixer node", err);
|
||||
|
||||
err = gMediaRoster->StopNode(video_window_node, 0, true);
|
||||
HandleError("Can't stop video window node", err);
|
||||
|
||||
// disconnect nodes
|
||||
|
||||
err = MediaRoster_Disconnect(video_output, video_input);
|
||||
HandleError("Can't disconnect video", err);
|
||||
|
||||
err = MediaRoster_Disconnect(audio_output, audio_input);
|
||||
HandleError("Can't disconnect audio", err);
|
||||
|
||||
// disable overlay, or erase image
|
||||
|
||||
fVideoView->RemoveVideoDisplay();
|
||||
|
||||
// release other nodes
|
||||
|
||||
err = gMediaRoster->ReleaseNode(audio_mixer_node);
|
||||
HandleError("Can't release audio mixer node", err);
|
||||
|
||||
// err = gMediaRoster->ReleaseNode(video_window_node);
|
||||
// HandleError("Can't release video window node", err);
|
||||
|
||||
// err = gMediaRoster->ReleaseNode(time_node);
|
||||
// HandleError("Can't release time source node", err);
|
||||
|
||||
// release dvb
|
||||
|
||||
err = gMediaRoster->ReleaseNode(dvb_node);
|
||||
HandleError("Can't release DVB node", err);
|
||||
|
||||
fConnected = false;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
MediaRoster_Disconnect(const media_output &output, const media_input &input)
|
||||
{
|
||||
if (output.node.node <= 0) {
|
||||
printf("MediaRoster_Disconnect: output.node.node %d invalid\n",
|
||||
(int)output.node.node);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (input.node.node <= 0) {
|
||||
printf("MediaRoster_Disconnect: input.node.node %d invalid\n",
|
||||
(int)input.node.node);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (!(output.node.kind & B_BUFFER_PRODUCER)) {
|
||||
printf("MediaRoster_Disconnect: output.node.kind 0x%x is no B_BUFFER_PRODUCER\n",
|
||||
(int)output.node.kind);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (!(input.node.kind & B_BUFFER_CONSUMER)) {
|
||||
printf("MediaRoster_Disconnect: input.node.kind 0x%x is no B_BUFFER_PRODUCER\n",
|
||||
(int)input.node.kind);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (input.source.port != output.source.port) {
|
||||
printf("MediaRoster_Disconnect: input.source.port %d doesn't match output.source.port %d\n",
|
||||
(int)input.source.port, (int)output.source.port);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (input.source.id != output.source.id) {
|
||||
printf("MediaRoster_Disconnect: input.source.id %d doesn't match output.source.id %d\n",
|
||||
(int)input.source.id, (int)output.source.id);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (input.destination.port != output.destination.port) {
|
||||
printf("MediaRoster_Disconnect: input.destination.port %d doesn't match output.destination.port %d\n",
|
||||
(int)input.destination.port, (int)output.destination.port);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
if (input.destination.id != output.destination.id) {
|
||||
printf("MediaRoster_Disconnect: input.destination.id %d doesn't match output.destination.id %d\n",
|
||||
(int)input.destination.id, (int)output.destination.id);
|
||||
return B_MEDIA_BAD_NODE;
|
||||
}
|
||||
return BMediaRoster::Roster()->Disconnect(output.node.node, output.source, input.node.node, input.destination);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CONTROLLER_H
|
||||
#define __CONTROLLER_H
|
||||
|
||||
#include <Entry.h>
|
||||
#include <MediaDefs.h>
|
||||
#include <MediaNode.h>
|
||||
|
||||
class VideoView;
|
||||
class VideoNode;
|
||||
|
||||
class Controller
|
||||
{
|
||||
public:
|
||||
Controller();
|
||||
virtual ~Controller();
|
||||
|
||||
void SetVideoView(VideoView *view);
|
||||
void SetVideoNode(VideoNode *node);
|
||||
|
||||
void DisconnectInterface();
|
||||
status_t ConnectInterface(int i);
|
||||
|
||||
bool IsInterfaceAvailable(int i);
|
||||
int CurrentInterface();
|
||||
|
||||
int ChannelCount();
|
||||
int CurrentChannel();
|
||||
status_t SelectChannel(int i);
|
||||
const char * ChannelName(int i);
|
||||
|
||||
void VolumeUp();
|
||||
void VolumeDown();
|
||||
|
||||
private:
|
||||
status_t ConnectNodes();
|
||||
status_t DisconnectNodes();
|
||||
|
||||
private:
|
||||
int fCurrentInterface;
|
||||
int fCurrentChannel;
|
||||
VideoView * fVideoView;
|
||||
VideoNode * fVideoNode;
|
||||
BParameterWeb * fWeb;
|
||||
BDiscreteParameter * fChannelParam;
|
||||
bool fConnected;
|
||||
media_input fInput;
|
||||
media_output fOutput;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
#include <Bitmap.h>
|
||||
|
||||
#include "ConvertBitmap.h"
|
||||
|
||||
status_t ConvertBitmap_YCbCr422_to_RGB32(BBitmap *dst, const BBitmap *src);
|
||||
|
||||
status_t
|
||||
ConvertBitmap(BBitmap *dst, const BBitmap *src)
|
||||
{
|
||||
if (dst->Bounds() != src->Bounds())
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (dst->ColorSpace() == src->ColorSpace() && dst->BytesPerRow() == src->BytesPerRow() ) {
|
||||
memcpy(dst->Bits(), src->Bits(), src->BitsLength());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (src->ColorSpace() == B_YCbCr422 && dst->ColorSpace() == B_RGB32)
|
||||
return ConvertBitmap_YCbCr422_to_RGB32(dst, src);
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ConvertBitmap_YCbCr422_to_RGB32(BBitmap *dst, const BBitmap *src)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CONVERT_BITMAP_H
|
||||
#define __CONVERT_BITMAP_H
|
||||
|
||||
status_t ConvertBitmap(BBitmap *dst, const BBitmap *src);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "DeviceRoster.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
|
||||
|
||||
DeviceRoster *gDeviceRoster;
|
||||
|
||||
|
||||
|
||||
DeviceRoster::DeviceRoster()
|
||||
{
|
||||
live_node_info info[MAX_DEVICE_COUNT];
|
||||
int32 info_count = MAX_DEVICE_COUNT;
|
||||
status_t err;
|
||||
err = MediaRoster()->GetLiveNodes(info, &info_count, NULL, NULL, "DVB*", B_BUFFER_PRODUCER | B_PHYSICAL_INPUT);
|
||||
if (err != B_OK || info_count < 1) {
|
||||
printf("Can't find live DVB node. Found %ld nodes, error %08lx (%s)\n", info_count, err, strerror(err));
|
||||
fDeviceCount = 0;
|
||||
} else {
|
||||
fDeviceCount = info_count;
|
||||
for (int i = 0; i < fDeviceCount; i++) {
|
||||
fDeviceInfo[i].node = info[i].node;
|
||||
strcpy(fDeviceInfo[i].name, info[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DeviceRoster::~DeviceRoster()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DeviceRoster::DeviceCount()
|
||||
{
|
||||
return fDeviceCount;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
DeviceRoster::DeviceName(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < fDeviceCount);
|
||||
return fDeviceInfo[i].name;
|
||||
}
|
||||
|
||||
|
||||
media_node
|
||||
DeviceRoster::DeviceNode(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < fDeviceCount);
|
||||
return fDeviceInfo[i].node;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DeviceRoster::IsRawAudioOutputFree(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < fDeviceCount);
|
||||
|
||||
media_output output;
|
||||
int32 count;
|
||||
status_t err;
|
||||
|
||||
err = MediaRoster()->GetFreeOutputsFor(fDeviceInfo[i].node, &output, 1, &count, B_MEDIA_RAW_AUDIO);
|
||||
return (err == B_OK) && (count == 1);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DeviceRoster::IsEncAudioOutputFree(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < fDeviceCount);
|
||||
|
||||
media_output output;
|
||||
int32 count;
|
||||
status_t err;
|
||||
|
||||
err = MediaRoster()->GetFreeOutputsFor(fDeviceInfo[i].node, &output, 1, &count, B_MEDIA_ENCODED_AUDIO);
|
||||
return (err == B_OK) && (count == 1);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DeviceRoster::IsRawVideoOutputFree(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < fDeviceCount);
|
||||
|
||||
media_output output;
|
||||
int32 count;
|
||||
status_t err;
|
||||
|
||||
err = MediaRoster()->GetFreeOutputsFor(fDeviceInfo[i].node, &output, 1, &count, B_MEDIA_RAW_VIDEO);
|
||||
return (err == B_OK) && (count == 1);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DeviceRoster::IsEncVideoOutputFree(int i)
|
||||
{
|
||||
ASSERT(i >= 0 && i < fDeviceCount);
|
||||
|
||||
media_output output;
|
||||
int32 count;
|
||||
status_t err;
|
||||
|
||||
err = MediaRoster()->GetFreeOutputsFor(fDeviceInfo[i].node, &output, 1, &count, B_MEDIA_ENCODED_VIDEO);
|
||||
return (err == B_OK) && (count == 1);
|
||||
}
|
||||
|
||||
|
||||
BMediaRoster *
|
||||
DeviceRoster::MediaRoster()
|
||||
{
|
||||
return BMediaRoster::Roster();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_ROSTER_H
|
||||
#define __DEVICE_ROSTER_H
|
||||
|
||||
#include <MediaRoster.h>
|
||||
|
||||
class DeviceRoster
|
||||
{
|
||||
public:
|
||||
DeviceRoster();
|
||||
~DeviceRoster();
|
||||
|
||||
int DeviceCount();
|
||||
|
||||
const char * DeviceName(int i);
|
||||
media_node DeviceNode(int i);
|
||||
|
||||
bool IsRawAudioOutputFree(int i);
|
||||
bool IsEncAudioOutputFree(int i);
|
||||
bool IsRawVideoOutputFree(int i);
|
||||
bool IsEncVideoOutputFree(int i);
|
||||
|
||||
public:
|
||||
BMediaRoster* MediaRoster();
|
||||
|
||||
private:
|
||||
enum { MAX_DEVICE_COUNT = 8 };
|
||||
|
||||
class device_info
|
||||
{
|
||||
public:
|
||||
media_node node;
|
||||
char name[B_MEDIA_NAME_LENGTH];
|
||||
};
|
||||
|
||||
private:
|
||||
device_info fDeviceInfo[MAX_DEVICE_COUNT];
|
||||
int fDeviceCount;
|
||||
};
|
||||
|
||||
extern DeviceRoster *gDeviceRoster;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <Path.h>
|
||||
#include <Entry.h>
|
||||
#include <Alert.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "MainApp.h"
|
||||
#include "config.h"
|
||||
#include "DeviceRoster.h"
|
||||
|
||||
MainApp *gMainApp;
|
||||
|
||||
bool gOverlayDisabled = false;
|
||||
|
||||
MainApp::MainApp()
|
||||
: BApplication(APP_SIG)
|
||||
{
|
||||
InitPrefs();
|
||||
|
||||
gDeviceRoster = new DeviceRoster;
|
||||
|
||||
fMainWindow = NewWindow();
|
||||
}
|
||||
|
||||
|
||||
MainApp::~MainApp()
|
||||
{
|
||||
delete gDeviceRoster;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
MainApp::InitPrefs()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BWindow *
|
||||
MainApp::NewWindow()
|
||||
{
|
||||
static int i = 0;
|
||||
BRect rect(200, 200, 750, 300);
|
||||
rect.OffsetBy(i * 25, i * 25);
|
||||
i = (i + 1) % 15;
|
||||
BWindow *win = new MainWin(rect);
|
||||
win->Show();
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
if (argc > 1)
|
||||
gOverlayDisabled = true;
|
||||
gMainApp = new MainApp;
|
||||
gMainApp->Run();
|
||||
delete gMainApp;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <[email protected]>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MAIN_APP_H
|
||||
#define __MAIN_APP_H
|
||||
|
||||
#include <Application.h>
|
||||
#include "MainWin.h"
|
||||
|
||||
class MainApp : public BApplication
|
||||
{
|
||||
public:
|
||||
MainApp();
|
||||
~MainApp();
|
||||
status_t InitPrefs();
|
||||
BWindow * NewWindow();
|
||||
|
||||
private:
|
||||
BWindow * fMainWindow;
|
||||
};
|
||||
|
||||
extern MainApp *gMainApp;
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MAIN_WIN_H
|
||||
#define __MAIN_WIN_H
|
||||
|
||||
#include <Window.h>
|
||||
#include <Menu.h>
|
||||
#include <Button.h>
|
||||
#include <Slider.h>
|
||||
#include "Controller.h"
|
||||
#include "VideoView.h"
|
||||
|
||||
class MainWin : public BWindow
|
||||
{
|
||||
public:
|
||||
MainWin(BRect rect);
|
||||
~MainWin();
|
||||
|
||||
void FrameResized(float new_width, float new_height);
|
||||
void Zoom(BPoint rec_position, float rec_width, float rec_height);
|
||||
void DispatchMessage(BMessage *message, BHandler *handler);
|
||||
void MessageReceived(BMessage *msg);
|
||||
bool QuitRequested();
|
||||
|
||||
void MouseDown(BMessage *msg);
|
||||
void MouseMoved(BMessage *msg);
|
||||
void MouseUp(BMessage *msg);
|
||||
status_t KeyDown(BMessage *msg);
|
||||
|
||||
void CreateMenu();
|
||||
|
||||
void SetupInterfaceMenu();
|
||||
void SetupChannelMenu();
|
||||
|
||||
void SelectInitialInterface();
|
||||
|
||||
void SelectInterface(int i);
|
||||
void SelectChannel(int i);
|
||||
|
||||
void SetInterfaceMenuMarker();
|
||||
void SetChannelMenuMarker();
|
||||
|
||||
void VideoFormatChange(int width, int height, float width_scale, float height_scale);
|
||||
|
||||
void UpdateWindowTitle();
|
||||
|
||||
void AdjustFullscreenRenderer();
|
||||
void AdjustWindowedRenderer(bool user_resized);
|
||||
|
||||
void ToggleFullscreen();
|
||||
void ToggleKeepAspectRatio();
|
||||
void ToggleAlwaysOnTop();
|
||||
void ToggleNoBorder();
|
||||
void ToggleNoMenu();
|
||||
void ToggleNoBorderNoMenu();
|
||||
|
||||
void ShowContextMenu(const BPoint &screen_point);
|
||||
|
||||
BMenuBar * fMenuBar;
|
||||
BView * fBackground;
|
||||
VideoView * fVideoView;
|
||||
|
||||
BMenu * fFileMenu;
|
||||
BMenu * fChannelMenu;
|
||||
BMenu * fInterfaceMenu;
|
||||
BMenu * fSettingsMenu;
|
||||
BMenu * fDebugMenu;
|
||||
|
||||
Controller * fController;
|
||||
volatile bool fIsFullscreen;
|
||||
volatile bool fKeepAspectRatio;
|
||||
volatile bool fAlwaysOnTop;
|
||||
volatile bool fNoMenu;
|
||||
volatile bool fNoBorder;
|
||||
int fSourceWidth;
|
||||
int fSourceHeight;
|
||||
float fWidthScale;
|
||||
float fHeightScale;
|
||||
int fMenuBarHeight;
|
||||
BRect fSavedFrame;
|
||||
bool fMouseDownTracking;
|
||||
BPoint fMouseDownMousePos;
|
||||
BPoint fMouseDownWindowPos;
|
||||
bool fFrameResizedTriggeredAutomatically;
|
||||
bool fIgnoreFrameResized;
|
||||
bool fFrameResizedCalled;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Window.h>
|
||||
#include <TimeSource.h>
|
||||
#include <MediaRoster.h>
|
||||
#include <BufferGroup.h>
|
||||
#include <Buffer.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Locker.h>
|
||||
#include <Debug.h>
|
||||
|
||||
#include "VideoNode.h"
|
||||
#include "VideoView.h"
|
||||
|
||||
void
|
||||
overlay_copy(uint32 lines, void *dst, uint32 dst_bpr, const void *src, uint32 src_bpr)
|
||||
{
|
||||
// bigtime_t start = system_time();
|
||||
int len = min_c(dst_bpr, src_bpr);
|
||||
// int len4 = len / 4;
|
||||
while (lines--) {
|
||||
/*
|
||||
// this does not copy the last few bytes, if length is not aligned to 4 bytes
|
||||
asm ("rep\n\t""movsl"
|
||||
:
|
||||
: "c" (len4), "S" (src), "D" (dst)
|
||||
: "eax");
|
||||
*/
|
||||
/*
|
||||
const uint32 *s4 = (const uint32 *)src;
|
||||
uint32 *d4 = (uint32 *)dst;
|
||||
for (int i = 0; i < len4; i++)
|
||||
d4[i] = s4[i];
|
||||
*/
|
||||
/*
|
||||
const uint8 *s1 = (const uint8 *)s4;
|
||||
uint8 *d1 = (uint8 *)d4;
|
||||
int l1 = len1;
|
||||
while (l1--)
|
||||
*d1++ = *s1++;
|
||||
*/
|
||||
memcpy(dst, src, len);
|
||||
src = (char *)src + src_bpr;
|
||||
dst = (char *)dst + dst_bpr;
|
||||
}
|
||||
// printf("overlay copy: %.06f sec\n", (system_time() - start) / 1000000.0);
|
||||
}
|
||||
|
||||
|
||||
VideoNode::VideoNode(const char *name, VideoView *view)
|
||||
: BMediaNode(name)
|
||||
, BMediaEventLooper()
|
||||
, BBufferConsumer(B_MEDIA_RAW_VIDEO)
|
||||
, fVideoView(view)
|
||||
, fInput()
|
||||
, fOverlayEnabled(true)
|
||||
, fOverlayActive(false)
|
||||
, fDirectOverlayBuffer(false)
|
||||
, fBitmap(0)
|
||||
, fBitmapLocker(new BLocker("Video Node Locker"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
VideoNode::~VideoNode()
|
||||
{
|
||||
Quit();
|
||||
DeleteBuffers();
|
||||
delete fBitmapLocker;
|
||||
}
|
||||
|
||||
|
||||
BMediaAddOn *
|
||||
VideoNode::AddOn(int32 *internal_id) const
|
||||
{
|
||||
*internal_id = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::NodeRegistered()
|
||||
{
|
||||
fInput.node = Node();
|
||||
fInput.source = media_source::null;
|
||||
fInput.destination.port = ControlPort();
|
||||
fInput.destination.id = 0;
|
||||
fInput.format.type = B_MEDIA_RAW_VIDEO;
|
||||
fInput.format.u.raw_video = media_raw_video_format::wildcard;
|
||||
strcpy(fInput.name, "video in");
|
||||
|
||||
SetPriority(B_DISPLAY_PRIORITY);
|
||||
Run();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::BufferReceived(BBuffer * buffer)
|
||||
{
|
||||
if (RunState() != B_STARTED) {
|
||||
buffer->Recycle();
|
||||
return;
|
||||
}
|
||||
if (fOverlayActive && fDirectOverlayBuffer) {
|
||||
HandleBuffer(buffer);
|
||||
} else {
|
||||
media_timed_event event(buffer->Header()->start_time,
|
||||
BTimedEventQueue::B_HANDLE_BUFFER,
|
||||
buffer,
|
||||
BTimedEventQueue::B_RECYCLE_BUFFER);
|
||||
EventQueue()->AddEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VideoNode::GetNextInput(int32 *cookie, media_input *out_input)
|
||||
{
|
||||
if (*cookie < 1) {
|
||||
*out_input = fInput;
|
||||
*cookie += 1;
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::DisposeInputCookie(int32 cookie)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VideoNode:: HandleMessage(int32 message,
|
||||
const void *data,
|
||||
size_t size)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::HandleEvent(const media_timed_event *event,
|
||||
bigtime_t lateness,
|
||||
bool realTimeEvent)
|
||||
{
|
||||
switch (event->type) {
|
||||
case BTimedEventQueue::B_START:
|
||||
break;
|
||||
case BTimedEventQueue::B_STOP:
|
||||
EventQueue()->FlushEvents(event->event_time, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
|
||||
break;
|
||||
case BTimedEventQueue::B_HANDLE_BUFFER:
|
||||
HandleBuffer((BBuffer *)event->pointer);
|
||||
break;
|
||||
default:
|
||||
printf("VideoNode::HandleEvent unknown event");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::ProducerDataStatus(const media_destination &dst,
|
||||
int32 status,
|
||||
bigtime_t at_media_time)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VideoNode::GetLatencyFor(const media_destination &dst,
|
||||
bigtime_t *out_latency,
|
||||
media_node_id *out_id)
|
||||
{
|
||||
if (dst != fInput.destination)
|
||||
return B_MEDIA_BAD_DESTINATION;
|
||||
|
||||
*out_latency = 10000;
|
||||
*out_id = TimeSource()->ID();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
VideoNode::AcceptFormat(const media_destination &dst,
|
||||
media_format *format)
|
||||
{
|
||||
/* The connection process:
|
||||
* BBufferProducer::FormatProposal
|
||||
* we are here => BBufferConsumer::AcceptFormat
|
||||
* BBufferProducer::PrepareToConnect
|
||||
* BBufferConsumer::Connected
|
||||
* BBufferProducer::Connect
|
||||
*/
|
||||
|
||||
if (dst != fInput.destination)
|
||||
return B_MEDIA_BAD_DESTINATION;
|
||||
|
||||
if (format->type == B_MEDIA_NO_TYPE)
|
||||
format->type = B_MEDIA_RAW_VIDEO;
|
||||
|
||||
if (format->type != B_MEDIA_RAW_VIDEO)
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VideoNode::Connected(const media_source &src,
|
||||
const media_destination &dst,
|
||||
const media_format &format,
|
||||
media_input *out_input)
|
||||
{
|
||||
/* The connection process:
|
||||
* BBufferProducer::FormatProposal
|
||||
* BBufferConsumer::AcceptFormat
|
||||
* BBufferProducer::PrepareToConnect
|
||||
* we are here => BBufferConsumer::Connected
|
||||
* BBufferProducer::Connect
|
||||
*/
|
||||
|
||||
if (dst != fInput.destination)
|
||||
return B_MEDIA_BAD_DESTINATION;
|
||||
|
||||
fInput.source = src;
|
||||
fInput.format = format;
|
||||
|
||||
if (fInput.format.u.raw_video.field_rate < 1.0)
|
||||
fInput.format.u.raw_video.field_rate = 25.0;
|
||||
|
||||
color_space colorspace = format.u.raw_video.display.format;
|
||||
BRect frame(0, 0, format.u.raw_video.display.line_width - 1, format.u.raw_video.display.line_count - 1);
|
||||
status_t err;
|
||||
|
||||
DeleteBuffers();
|
||||
err = CreateBuffers(frame, colorspace, fOverlayEnabled);
|
||||
if (err) {
|
||||
printf("VideoNode::Connected failed, fOverlayEnabled = %d\n", fOverlayEnabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
*out_input = fInput;
|
||||
|
||||
return B_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::Disconnected(const media_source &src,
|
||||
const media_destination &dst)
|
||||
{
|
||||
if (src != fInput.source)
|
||||
return;
|
||||
if (dst != fInput.destination)
|
||||
return;
|
||||
|
||||
DeleteBuffers();
|
||||
|
||||
// disconnect the connection
|
||||
fInput.source = media_source::null;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VideoNode::FormatChanged(const media_source &src,
|
||||
const media_destination &dst,
|
||||
int32 from_change_count,
|
||||
const media_format &format)
|
||||
{
|
||||
printf("VideoNode::FormatChanged enter\n");
|
||||
if (src != fInput.source)
|
||||
return B_MEDIA_BAD_SOURCE;
|
||||
if (dst != fInput.destination)
|
||||
return B_MEDIA_BAD_DESTINATION;
|
||||
|
||||
color_space colorspace = format.u.raw_video.display.format;
|
||||
BRect frame(0, 0, format.u.raw_video.display.line_width - 1, format.u.raw_video.display.line_count - 1);
|
||||
status_t err;
|
||||
|
||||
DeleteBuffers();
|
||||
if (fOverlayEnabled) {
|
||||
fVideoView->RemoveOverlay();
|
||||
err = CreateBuffers(frame, colorspace, true); // try overlay
|
||||
if (err) {
|
||||
printf("VideoNode::FormatChanged creating overlay buffer failed\n");
|
||||
err = CreateBuffers(frame, colorspace, false); // no overlay
|
||||
}
|
||||
} else {
|
||||
err = CreateBuffers(frame, colorspace, false); // no overlay
|
||||
}
|
||||
if (err) {
|
||||
printf("VideoNode::FormatChanged failed (lost buffer group!)\n");
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
|
||||
fInput.format = format;
|
||||
|
||||
printf("VideoNode::FormatChanged leave\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::HandleBuffer(BBuffer *buffer)
|
||||
{
|
||||
// printf("VideoNode::HandleBuffer\n");
|
||||
|
||||
LockBitmap();
|
||||
if (fBitmap) {
|
||||
// bigtime_t start = system_time();
|
||||
if (fOverlayActive) {
|
||||
if (B_OK == fBitmap->LockBits()) {
|
||||
|
||||
// memcpy(fBitmap->Bits(), buffer->Data(), fBitmap->BitsLength());
|
||||
|
||||
// fBitmap->SetBits(buffer->Data(), fBitmap->BitsLength(), 0, fInput.format.u.raw_video.display.format);
|
||||
|
||||
overlay_copy(fBitmap->Bounds().IntegerHeight() + 1,
|
||||
fBitmap->Bits(), fBitmap->BytesPerRow(),
|
||||
buffer->Data(), fInput.format.u.raw_video.display.bytes_per_row);
|
||||
|
||||
|
||||
fBitmap->UnlockBits();
|
||||
}
|
||||
} else {
|
||||
// memcpy(fBitmap->Bits(), buffer->Data(), fBitmap->BitsLength());
|
||||
|
||||
overlay_copy(fBitmap->Bounds().IntegerHeight() + 1,
|
||||
fBitmap->Bits(), fBitmap->BytesPerRow(),
|
||||
buffer->Data(), fInput.format.u.raw_video.display.bytes_per_row);
|
||||
}
|
||||
// printf("overlay copy: %Ld usec\n", system_time() - start);
|
||||
}
|
||||
UnlockBitmap();
|
||||
|
||||
buffer->Recycle();
|
||||
|
||||
fVideoView->DrawFrame();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::SetOverlayEnabled(bool yesno)
|
||||
{
|
||||
fOverlayEnabled = yesno;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::LockBitmap()
|
||||
{
|
||||
fBitmapLocker->Lock();
|
||||
}
|
||||
|
||||
|
||||
BBitmap *
|
||||
VideoNode::Bitmap()
|
||||
{
|
||||
return fBitmap;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::UnlockBitmap()
|
||||
{
|
||||
fBitmapLocker->Unlock();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
VideoNode::IsOverlayActive()
|
||||
{
|
||||
return fOverlayActive;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VideoNode::CreateBuffers(BRect frame, color_space cspace, bool overlay)
|
||||
{
|
||||
printf("VideoNode::CreateBuffers: frame %d,%d,%d,%d colorspace 0x%08x, overlay %d\n",
|
||||
int(frame.left), int(frame.top), int(frame.right), int(frame.bottom), int(cspace), overlay);
|
||||
|
||||
// int32 bytesPerRow = B_ANY_BYTES_PER_ROW;
|
||||
// if (cspace == B_YCbCr422)
|
||||
// bytesPerRow = (int(frame.Width()) + 1) * 2;
|
||||
|
||||
// printf("overlay bitmap: requesting: bytes per row: %d\n", bytesPerRow);
|
||||
|
||||
LockBitmap();
|
||||
ASSERT(fBitmap == 0);
|
||||
uint32 flags = overlay ? (B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL) : 0;
|
||||
// fBitmap = new BBitmap(frame, flags, cspace, bytesPerRow);
|
||||
fBitmap = new BBitmap(frame, flags, cspace);
|
||||
if (!(fBitmap && fBitmap->InitCheck() == B_OK && fBitmap->IsValid())) {
|
||||
delete fBitmap;
|
||||
fBitmap = 0;
|
||||
fOverlayActive = false;
|
||||
UnlockBitmap();
|
||||
printf("VideoNode::CreateBuffers failed\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
printf("overlay bitmap: got: bytes per row: %d\n", fBitmap->BytesPerRow());
|
||||
fOverlayActive = overlay;
|
||||
UnlockBitmap();
|
||||
printf("VideoNode::CreateBuffers success\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoNode::DeleteBuffers()
|
||||
{
|
||||
LockBitmap();
|
||||
delete fBitmap;
|
||||
fBitmap = NULL;
|
||||
UnlockBitmap();
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __VIDEO_NODE_H_
|
||||
#define __VIDEO_NODE_H_
|
||||
|
||||
#include <BufferConsumer.h>
|
||||
#include <MediaEventLooper.h>
|
||||
|
||||
class VideoView;
|
||||
|
||||
class VideoNode : public BMediaEventLooper, public BBufferConsumer
|
||||
{
|
||||
public:
|
||||
VideoNode(const char *name, VideoView *view);
|
||||
~VideoNode();
|
||||
|
||||
void SetOverlayEnabled(bool yesno);
|
||||
bool IsOverlayActive();
|
||||
|
||||
void LockBitmap();
|
||||
BBitmap * Bitmap();
|
||||
void UnlockBitmap();
|
||||
|
||||
protected:
|
||||
BMediaAddOn * AddOn(int32 *internal_id) const;
|
||||
|
||||
void NodeRegistered();
|
||||
|
||||
void BufferReceived(BBuffer * buffer);
|
||||
|
||||
status_t GetNextInput(int32 *cookie, media_input *out_input);
|
||||
void DisposeInputCookie(int32 cookie);
|
||||
|
||||
status_t HandleMessage(
|
||||
int32 message,
|
||||
const void *data,
|
||||
size_t size);
|
||||
|
||||
void HandleEvent(
|
||||
const media_timed_event *event,
|
||||
bigtime_t lateness,
|
||||
bool realTimeEvent);
|
||||
|
||||
status_t AcceptFormat(
|
||||
const media_destination &dst,
|
||||
media_format *format);
|
||||
|
||||
void ProducerDataStatus(
|
||||
const media_destination &dst,
|
||||
int32 status,
|
||||
bigtime_t at_media_time);
|
||||
|
||||
status_t GetLatencyFor(
|
||||
const media_destination &dst,
|
||||
bigtime_t *out_latency,
|
||||
media_node_id *out_id);
|
||||
|
||||
status_t Connected(
|
||||
const media_source &src,
|
||||
const media_destination &dst,
|
||||
const media_format &format,
|
||||
media_input *out_input);
|
||||
|
||||
void Disconnected(
|
||||
const media_source &src,
|
||||
const media_destination &dst);
|
||||
|
||||
status_t FormatChanged(
|
||||
const media_source &src,
|
||||
const media_destination &dst,
|
||||
int32 from_change_count,
|
||||
const media_format &format);
|
||||
|
||||
protected:
|
||||
void HandleBuffer(BBuffer *buffer);
|
||||
status_t CreateBuffers(BRect frame, color_space cspace, bool overlay);
|
||||
void DeleteBuffers();
|
||||
|
||||
protected:
|
||||
VideoView * fVideoView;
|
||||
media_input fInput;
|
||||
bool fOverlayEnabled;
|
||||
bool fOverlayActive;
|
||||
bool fDirectOverlayBuffer; // If the overlay memory is directly written by the producer node.
|
||||
BBitmap * fBitmap;
|
||||
BLocker * fBitmapLocker;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <MediaRoster.h>
|
||||
#include <MessageRunner.h>
|
||||
#include "VideoView.h"
|
||||
#include "VideoNode.h"
|
||||
#include "ConvertBitmap.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK_ACTIVITY 'ChkA'
|
||||
|
||||
VideoView::VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags)
|
||||
: BView(frame, name, resizeMask, flags)
|
||||
, fVideoNode(0)
|
||||
, fVideoActive(false)
|
||||
, fOverlayActive(false)
|
||||
, fActivityCheckMsgRunner(0)
|
||||
, fLastFrame(0)
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
|
||||
status_t err = B_OK;
|
||||
BMediaRoster *mroster = BMediaRoster::Roster(&err);
|
||||
if (!mroster || err) {
|
||||
printf("VideoView::VideoView: media_server is dead\n");
|
||||
exit(1);
|
||||
} else {
|
||||
fVideoNode = new VideoNode("video in", this);
|
||||
err = mroster->RegisterNode(fVideoNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VideoView::~VideoView()
|
||||
{
|
||||
delete fActivityCheckMsgRunner;
|
||||
|
||||
if (fVideoNode) {
|
||||
BMediaRoster::Roster()->UnregisterNode(fVideoNode);
|
||||
delete fVideoNode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::AttachedToWindow()
|
||||
{
|
||||
BMessage msg(CHECK_ACTIVITY);
|
||||
fActivityCheckMsgRunner = new BMessageRunner(BMessenger(this), &msg, 200000);
|
||||
}
|
||||
|
||||
|
||||
VideoNode *
|
||||
VideoView::Node()
|
||||
{
|
||||
return fVideoNode;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::OverlayLockAcquire()
|
||||
{
|
||||
printf("VideoView::OverlayLockAcquire\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::OverlayLockRelease()
|
||||
{ /* [19:54] <Francois> Rudolf forwarded me a mail once about it
|
||||
* [19:55] <Francois> when you get relmease msg you are supposed to UnlockBits() on the overlay bitmaps you use
|
||||
* [19:55] <Francois> it's used when switching workspaces
|
||||
* [19:55] <Francois> as the bits might get relocated
|
||||
*/
|
||||
printf("VideoView::OverlayLockRelease\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::OverlayScreenshotPrepare()
|
||||
{
|
||||
printf("OverlayScreenshotPrepare enter\n");
|
||||
/*
|
||||
fVideoNode->LockBitmap();
|
||||
if (fOverlayActive) {
|
||||
BBitmap *bmp = fVideoNode->Bitmap();
|
||||
if (bmp) {
|
||||
// Window()->UpdateIfNeeded();
|
||||
// Sync();
|
||||
BBitmap *tmp = new BBitmap(bmp->Bounds(), 0, B_RGB32);
|
||||
// ConvertBitmap(tmp, bmp);
|
||||
ClearViewOverlay();
|
||||
DrawBitmap(tmp, Bounds());
|
||||
delete tmp;
|
||||
// Sync();
|
||||
}
|
||||
}
|
||||
fVideoNode->UnlockBitmap();
|
||||
*/
|
||||
printf("OverlayScreenshotPrepare leave\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::OverlayScreenshotCleanup()
|
||||
{
|
||||
printf("OverlayScreenshotCleanup enter\n");
|
||||
/*
|
||||
snooze(50000); // give app server some time to take the screenshot
|
||||
fVideoNode->LockBitmap();
|
||||
if (fOverlayActive) {
|
||||
BBitmap *bmp = fVideoNode->Bitmap();
|
||||
if (bmp) {
|
||||
DrawBitmap(bmp, Bounds());
|
||||
SetViewOverlay(bmp, bmp->Bounds(), Bounds(), &fOverlayKeyColor,
|
||||
B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
fVideoNode->UnlockBitmap();
|
||||
*/
|
||||
printf("OverlayScreenshotCleanup leave\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::RemoveVideoDisplay()
|
||||
{
|
||||
printf("VideoView::RemoveVideoDisplay\n");
|
||||
|
||||
if (fOverlayActive) {
|
||||
ClearViewOverlay();
|
||||
fOverlayActive = false;
|
||||
}
|
||||
fVideoActive = false;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::RemoveOverlay()
|
||||
{
|
||||
printf("VideoView::RemoveOverlay\n");
|
||||
if (LockLooperWithTimeout(50000) == B_OK) {
|
||||
ClearViewOverlay();
|
||||
fOverlayActive = false;
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::CheckActivity()
|
||||
{
|
||||
if (!fVideoActive)
|
||||
return;
|
||||
if (system_time() - fLastFrame < 700000)
|
||||
return;
|
||||
|
||||
printf("VideoView::CheckActivity: lag detected\n");
|
||||
|
||||
fVideoActive = false;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::Draw(BRect updateRect)
|
||||
{
|
||||
if (!fVideoActive) {
|
||||
DrawTestImage();
|
||||
return;
|
||||
}
|
||||
if (fOverlayActive) {
|
||||
SetHighColor(fOverlayKeyColor);
|
||||
FillRect(updateRect);
|
||||
} else {
|
||||
fVideoNode->LockBitmap();
|
||||
BBitmap *bmp = fVideoNode->Bitmap();
|
||||
if (bmp)
|
||||
DrawBitmap(bmp, Bounds());
|
||||
fVideoNode->UnlockBitmap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::DrawFrame()
|
||||
{
|
||||
// printf("VideoView::DrawFrame\n");
|
||||
if (!fVideoActive) {
|
||||
fVideoActive = true;
|
||||
if (LockLooperWithTimeout(50000) != B_OK)
|
||||
return;
|
||||
Invalidate();
|
||||
UnlockLooper();
|
||||
}
|
||||
fLastFrame = system_time();
|
||||
|
||||
bool want_overlay = fVideoNode->IsOverlayActive();
|
||||
|
||||
if (!want_overlay && fOverlayActive) {
|
||||
if (LockLooperWithTimeout(50000) == B_OK) {
|
||||
ClearViewOverlay();
|
||||
UnlockLooper();
|
||||
fOverlayActive = false;
|
||||
} else {
|
||||
printf("can't ClearViewOverlay, as LockLooperWithTimeout failed\n");
|
||||
}
|
||||
}
|
||||
if (want_overlay && !fOverlayActive) {
|
||||
fVideoNode->LockBitmap();
|
||||
BBitmap *bmp = fVideoNode->Bitmap();
|
||||
if (bmp && LockLooperWithTimeout(50000) == B_OK) {
|
||||
SetViewOverlay(bmp, bmp->Bounds(), Bounds(), &fOverlayKeyColor,
|
||||
B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL | B_OVERLAY_FILTER_VERTICAL);
|
||||
fOverlayActive = true;
|
||||
|
||||
Invalidate();
|
||||
UnlockLooper();
|
||||
}
|
||||
fVideoNode->UnlockBitmap();
|
||||
}
|
||||
if (!fOverlayActive) {
|
||||
if (LockLooperWithTimeout(50000) != B_OK)
|
||||
return;
|
||||
Invalidate();
|
||||
UnlockLooper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::DrawTestImage()
|
||||
{
|
||||
static const rgb_color cols[8] = {
|
||||
{255,255,255}, {255,255,0}, {0,255,255}, {0,255,0},
|
||||
{255,0,255}, {255,0,0}, {0,0,255}, {0,0,0}
|
||||
// {255,255,255}, {255,255,0}, {0,255,255},
|
||||
// {255,0,255}, {255,0,0}, {0,255,0}, {0,0,255}, {0,0,0}
|
||||
};
|
||||
float bar_width;
|
||||
float left;
|
||||
float right;
|
||||
|
||||
BRect bnd = Bounds();
|
||||
int seperator_y1 = int(0.60 * (bnd.Height() + 1));
|
||||
int seperator_y2 = int(0.80 * (bnd.Height() + 1));
|
||||
int steps;
|
||||
|
||||
bar_width = bnd.Width() / 8;
|
||||
if (bar_width < 1)
|
||||
bar_width = 1;
|
||||
|
||||
left = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
SetHighColor(cols[i]);
|
||||
right = (i != 7) ? left + bar_width - 1 : bnd.right;
|
||||
FillRect(BRect(left, 0, right, seperator_y1));
|
||||
left = right + 1;
|
||||
}
|
||||
|
||||
steps = 32;
|
||||
|
||||
bar_width = bnd.Width() / steps;
|
||||
// if (bar_width < 1)
|
||||
// bar_width = 1;
|
||||
|
||||
left = 0;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
uint8 c = i * 255 / (steps - 1);
|
||||
SetHighColor(c, c, c);
|
||||
right = (i != steps - 1) ? left + bar_width - 1 : bnd.right;
|
||||
FillRect(BRect(left, seperator_y1 + 1, right, seperator_y2));
|
||||
left = right + 1;
|
||||
}
|
||||
|
||||
steps = 256;
|
||||
|
||||
bar_width = bnd.Width() / steps;
|
||||
if (bar_width < 1)
|
||||
bar_width = 1;
|
||||
|
||||
left = 0;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
uint8 c = 255 - (i * 255 / (steps - 1));
|
||||
SetHighColor(c, c, c);
|
||||
right = (i != steps - 1) ? left + bar_width - 1 : bnd.right;
|
||||
FillRect(BRect(left, seperator_y2 + 1, right, bnd.bottom));
|
||||
left = right + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoView::MessageReceived(BMessage *msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case CHECK_ACTIVITY:
|
||||
CheckActivity();
|
||||
break;
|
||||
default:
|
||||
BView::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
VideoView::IsOverlaySupported()
|
||||
{
|
||||
struct colorcombo {
|
||||
color_space colspace;
|
||||
const char *name;
|
||||
} colspace[] = {
|
||||
{ B_RGB32, "B_RGB32"},
|
||||
{ B_RGBA32, "B_RGBA32"},
|
||||
{ B_RGB24, "B_RGB24"},
|
||||
{ B_RGB16, "B_RGB16"},
|
||||
{ B_RGB15, "B_RGB15"},
|
||||
{ B_RGBA15, "B_RGBA15"},
|
||||
{ B_RGB32_BIG, "B_RGB32_BIG"},
|
||||
{ B_RGBA32_BIG, "B_RGBA32_BIG "},
|
||||
{ B_RGB24_BIG, "B_RGB24_BIG "},
|
||||
{ B_RGB16_BIG, "B_RGB16_BIG "},
|
||||
{ B_RGB15_BIG, "B_RGB15_BIG "},
|
||||
{ B_RGBA15_BIG, "B_RGBA15_BIG "},
|
||||
{ B_YCbCr422, "B_YCbCr422"},
|
||||
{ B_YCbCr411, "B_YCbCr411"},
|
||||
{ B_YCbCr444, "B_YCbCr444"},
|
||||
{ B_YCbCr420, "B_YCbCr420"},
|
||||
{ B_YUV422, "B_YUV422"},
|
||||
{ B_YUV411, "B_YUV411"},
|
||||
{ B_YUV444, "B_YUV444"},
|
||||
{ B_YUV420, "B_YUV420"},
|
||||
{ B_NO_COLOR_SPACE, NULL}
|
||||
};
|
||||
|
||||
bool supported = false;
|
||||
for (int i = 0; colspace[i].name; i++) {
|
||||
BBitmap *test = new BBitmap(BRect(0,0,320,240), B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL, colspace[i].colspace);
|
||||
if (test->InitCheck() == B_OK) {
|
||||
printf("Display supports %s (0x%08x) overlay\n", colspace[i].name, colspace[i].colspace);
|
||||
overlay_restrictions restrict;
|
||||
if (B_OK == test->GetOverlayRestrictions(&restrict)) {
|
||||
printf("Overlay restrictions: source horizontal_alignment %d\n", restrict.source.horizontal_alignment);
|
||||
printf("Overlay restrictions: source vertical_alignment %d\n", restrict.source.vertical_alignment);
|
||||
printf("Overlay restrictions: source width_alignment %d\n", restrict.source.width_alignment);
|
||||
printf("Overlay restrictions: source height_alignment %d\n", restrict.source.height_alignment);
|
||||
printf("Overlay restrictions: source min_width %d\n", restrict.source.min_width);
|
||||
printf("Overlay restrictions: source max_width %d\n", restrict.source.max_width);
|
||||
printf("Overlay restrictions: source min_height %d\n", restrict.source.min_height);
|
||||
printf("Overlay restrictions: source max_height %d\n", restrict.source.max_height);
|
||||
printf("Overlay restrictions: destination horizontal_alignment %d\n", restrict.destination.horizontal_alignment);
|
||||
printf("Overlay restrictions: destination vertical_alignment %d\n", restrict.destination.vertical_alignment);
|
||||
printf("Overlay restrictions: destination width_alignment %d\n", restrict.destination.width_alignment);
|
||||
printf("Overlay restrictions: destination height_alignment %d\n", restrict.destination.height_alignment);
|
||||
printf("Overlay restrictions: destination min_width %d\n", restrict.destination.min_width);
|
||||
printf("Overlay restrictions: destination max_width %d\n", restrict.destination.max_width);
|
||||
printf("Overlay restrictions: destination min_height %d\n", restrict.destination.min_height);
|
||||
printf("Overlay restrictions: destination max_height %d\n", restrict.destination.max_height);
|
||||
printf("Overlay restrictions: min_width_scale %d\n", restrict.min_width_scale);
|
||||
printf("Overlay restrictions: max_width_scale %d\n", restrict.max_width_scale);
|
||||
printf("Overlay restrictions: min_height_scale %d\n", restrict.min_height_scale);
|
||||
printf("Overlay restrictions: max_height_scale %d\n", restrict.max_height_scale);
|
||||
}
|
||||
supported = true;
|
||||
}
|
||||
delete test;
|
||||
// if (supported)
|
||||
// break;
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __VIDEO_VIEW_H
|
||||
#define __VIDEO_VIEW_H
|
||||
|
||||
#include <View.h>
|
||||
|
||||
class VideoNode;
|
||||
|
||||
class VideoView : public BView
|
||||
{
|
||||
public:
|
||||
VideoView(BRect frame, const char *name, uint32 resizeMask, uint32 flags);
|
||||
~VideoView();
|
||||
|
||||
void RemoveVideoDisplay();
|
||||
void RemoveOverlay();
|
||||
|
||||
VideoNode * Node();
|
||||
|
||||
bool IsOverlaySupported();
|
||||
|
||||
void OverlayLockAcquire();
|
||||
void OverlayLockRelease();
|
||||
|
||||
void OverlayScreenshotPrepare();
|
||||
void OverlayScreenshotCleanup();
|
||||
|
||||
void DrawFrame();
|
||||
|
||||
private:
|
||||
void AttachedToWindow();
|
||||
void MessageReceived(BMessage *msg);
|
||||
void Draw(BRect updateRect);
|
||||
|
||||
void DrawTestImage();
|
||||
|
||||
void CheckActivity();
|
||||
|
||||
private:
|
||||
VideoNode * fVideoNode;
|
||||
bool fVideoActive;
|
||||
bool fOverlayActive;
|
||||
rgb_color fOverlayKeyColor;
|
||||
BMessageRunner *fActivityCheckMsgRunner;
|
||||
bigtime_t fLastFrame;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
#include <InterfaceDefs.h>
|
||||
#include <time.h>
|
||||
#include "revision.h"
|
||||
|
||||
#define NAME "TV-O-Rama"
|
||||
#define VERSION "1.1"
|
||||
#define BUILD __DATE__ " "__TIME__
|
||||
#define COPYRIGHT B_UTF8_COPYRIGHT" Marcus Overhagen 2005-2006"
|
||||
#define INFO1 "DVB - Digital Video Broadcasting TV"
|
||||
#define APP_SIG "application/x-vnd.MarcusOverhagen."##NAME
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user