Files
haiku-beta6/src/apps/mediaplayer/Controller.cpp
T

419 lines
7.2 KiB
C++
Raw Normal View History

/*
* Controller.cpp - Media Player for the Haiku Operating System
*
* Copyright (C) 2006 Marcus Overhagen <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdio.h>
#include <string.h>
#include <Debug.h>
2006-05-07 21:08:01 +00:00
#include <Entry.h>
2006-05-06 21:17:42 +00:00
#include <MediaFile.h>
#include <MediaTrack.h>
#include "Controller.h"
#include "VideoView.h"
2006-05-07 21:08:01 +00:00
#include "SoundOutput.h"
2006-05-07 20:41:07 +00:00
#define AUDIO_PRIORITY 10
#define VIDEO_PRIORITY 10
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()
: fVideoView(NULL)
2006-05-07 21:08:01 +00:00
, fName()
2006-05-06 21:17:42 +00:00
, fPaused(false)
, fStopped(true)
, fMediaFile(0)
, fAudioTrack(0)
, fVideoTrack(0)
, fAudioTrackList(new BList)
, fVideoTrackList(new BList)
, fPosition(0)
, fAudioPlaySem(create_sem(1, "audio playing"))
, fVideoPlaySem(create_sem(1, "video playing"))
2006-05-07 20:41:07 +00:00
, fAudioPlayThread(-1)
, fVideoPlayThread(-1)
, fStopAudioPlayback(false)
, fStopVideoPlayback(false)
{
}
Controller::~Controller()
{
2006-05-07 20:41:07 +00:00
StopAudioPlayback();
StopVideoPlayback();
2006-05-06 21:17:42 +00:00
if (fMediaFile)
fMediaFile->ReleaseAllTracks();
delete fMediaFile;
delete fAudioTrackList;
delete fVideoTrackList;
delete_sem(fVideoPlaySem);
delete_sem(fAudioPlaySem);
}
void
Controller::SetVideoView(VideoView *view)
{
fVideoView = view;
}
status_t
Controller::SetTo(const entry_ref &ref)
{
2006-05-06 21:17:42 +00:00
acquire_sem(fAudioPlaySem);
acquire_sem(fVideoPlaySem);
2006-05-07 22:05:23 +00:00
StopAudioPlayback();
StopVideoPlayback();
2006-05-06 21:17:42 +00:00
fAudioTrackList->MakeEmpty();
fVideoTrackList->MakeEmpty();
if (fMediaFile)
fMediaFile->ReleaseAllTracks();
delete fMediaFile;
fAudioTrack = 0;
fVideoTrack = 0;
fMediaFile = 0;
fPosition = 0;
fPaused = false;
fStopped = true;
2006-05-07 21:08:01 +00:00
fName = ref.name;
2006-05-06 21:17:42 +00:00
status_t err;
BMediaFile *mf = new BMediaFile(&ref);
err = mf->InitCheck();
if (err != B_OK) {
printf("Controller::SetTo: initcheck failed\n");
delete mf;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return err;
}
int trackcount = mf->CountTracks();
if (trackcount <= 0) {
printf("Controller::SetTo: trackcount %d\n", trackcount);
delete mf;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return B_MEDIA_NO_HANDLER;
}
for (int i = 0; i < trackcount; i++) {
BMediaTrack *t = mf->TrackAt(i);
media_format f;
err = t->EncodedFormat(&f);
if (err != B_OK) {
printf("Controller::SetTo: EncodedFormat failed for track index %d, error 0x%08lx (%s)\n",
i, err, strerror(err));
mf->ReleaseTrack(t);
continue;
}
if (f.IsAudio()) {
fAudioTrackList->AddItem(t);
} else if (f.IsVideo()) {
fVideoTrackList->AddItem(t);
} else {
printf("Controller::SetTo: track index %d has unknown type\n", i);
mf->ReleaseTrack(t);
}
}
if (AudioTrackCount() == 0 && VideoTrackCount() == 0) {
printf("Controller::SetTo: no audio or video tracks found\n");
delete mf;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return B_MEDIA_NO_HANDLER;
}
printf("Controller::SetTo: %d audio track, %d video track\n", AudioTrackCount(), VideoTrackCount());
fMediaFile = mf;
SelectAudioTrack(0);
SelectVideoTrack(0);
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
return B_OK;
}
int
Controller::VideoTrackCount()
{
2006-05-06 21:17:42 +00:00
return fVideoTrackList->CountItems();
}
int
Controller::AudioTrackCount()
{
2006-05-06 21:17:42 +00:00
return fAudioTrackList->CountItems();
}
status_t
Controller::SelectAudioTrack(int n)
{
2006-05-07 21:08:01 +00:00
StopAudioPlayback();
2006-05-06 21:17:42 +00:00
BMediaTrack *t = (BMediaTrack *)fAudioTrackList->ItemAt(n);
if (!t)
return B_ERROR;
fAudioTrack = t;
2006-05-07 21:08:01 +00:00
StartAudioPlayback();
2006-05-06 21:17:42 +00:00
return B_OK;
}
status_t
Controller::SelectVideoTrack(int n)
{
2006-05-07 21:08:01 +00:00
StopVideoPlayback();
2006-05-06 21:17:42 +00:00
BMediaTrack *t = (BMediaTrack *)fVideoTrackList->ItemAt(n);
if (!t)
return B_ERROR;
fVideoTrack = t;
2006-05-07 21:08:01 +00:00
StartVideoPlayback();
2006-05-06 21:17:42 +00:00
return B_OK;
}
bigtime_t
Controller::Duration()
{
bigtime_t a = fAudioTrack ? fAudioTrack->Duration() : 0;
bigtime_t v = fVideoTrack ? fVideoTrack->Duration() : 0;
printf("Controller::Duration: audio %.6f, video %.6f", a / 1000000.0, v / 1000000.0);
return max_c(a, v);
}
bigtime_t
Controller::Position()
{
return fPosition;
}
status_t
Controller::Seek(bigtime_t pos)
{
return B_OK;
}
void
Controller::VolumeUp()
{
}
void
Controller::VolumeDown()
{
}
bool
Controller::IsOverlayActive()
{
return true;
}
void
Controller::LockBitmap()
{
}
void
Controller::UnlockBitmap()
{
}
BBitmap *
Controller::Bitmap()
{
return NULL;
}
2006-04-24 20:47:29 +00:00
void
Controller::Stop()
{
2006-05-06 21:17:42 +00:00
if (fStopped)
return;
acquire_sem(fAudioPlaySem);
acquire_sem(fVideoPlaySem);
fPaused = false;
fStopped = true;
fPosition = 0;
2006-04-24 20:47:29 +00:00
}
void
Controller::Play()
{
2006-05-06 21:17:42 +00:00
if (!fPaused && !fStopped)
return;
fStopped =
fPaused = false;
release_sem(fAudioPlaySem);
release_sem(fVideoPlaySem);
2006-04-24 20:47:29 +00:00
}
void
Controller::Pause()
{
2006-05-06 21:17:42 +00:00
if (fStopped || fPaused)
return;
acquire_sem(fAudioPlaySem);
acquire_sem(fVideoPlaySem);
fPaused = true;
2006-04-24 20:47:29 +00:00
}
bool
Controller::IsPaused()
{
2006-05-06 21:17:42 +00:00
return fPaused;
2006-04-24 20:47:29 +00:00
}
int32
Controller::audio_play_thread(void *self)
{
static_cast<Controller *>(self)->AudioPlayThread();
return 0;
}
int32
Controller::video_play_thread(void *self)
{
static_cast<Controller *>(self)->VideoPlayThread();
return 0;
}
void
Controller::AudioPlayThread()
{
2006-05-07 21:08:01 +00:00
// this is a test...
media_format fmt;
fmt.type = B_MEDIA_RAW_AUDIO;
fmt.u.raw_audio = media_multi_audio_format::wildcard;
fmt.u.raw_audio.format = media_multi_audio_format::B_AUDIO_FLOAT;
fAudioTrack->DecodedFormat(&fmt);
SoundOutput out(fName.String(), fmt.u.raw_audio);
int frame_size = (fmt.u.raw_audio.format & 0xf) * fmt.u.raw_audio.channel_count;
uint8 buffer[fmt.u.raw_audio.buffer_size];
int64 frames;
media_header mh;
while (!fStopAudioPlayback && B_OK == fAudioTrack->ReadFrames(buffer, &frames, &mh)) {
out.Play(buffer, frames * frame_size);
}
}
void
Controller::VideoPlayThread()
{
}
2006-05-07 20:41:07 +00:00
void
Controller::StartAudioPlayback()
{
if (fAudioPlayThread > 0)
return;
fStopAudioPlayback = false;
fAudioPlayThread = spawn_thread(audio_play_thread, "audio playback", AUDIO_PRIORITY, this);
resume_thread(fAudioPlayThread);
}
void
Controller::StartVideoPlayback()
{
if (fVideoPlayThread > 0)
return;
fStopVideoPlayback = false;
fVideoPlayThread = spawn_thread(video_play_thread, "video playback", VIDEO_PRIORITY, this);
resume_thread(fVideoPlayThread);
}
void
Controller::StopAudioPlayback()
{
if (fAudioPlayThread < 0)
return;
fStopAudioPlayback = true;
status_t dummy;
wait_for_thread(fAudioPlayThread, &dummy);
fAudioPlayThread = -1;
}
void
Controller::StopVideoPlayback()
{
if (fVideoPlayThread < 0)
return;
fStopVideoPlayback = true;
status_t dummy;
wait_for_thread(fVideoPlayThread, &dummy);
fVideoPlayThread = -1;
}