xref: /haiku/src/servers/media_addon/MediaFilePlayer.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
1 /*
2  * Copyright (c) 2004, Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
3  * Copyright (c) 2007, Jérôme Duval. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include <MediaFiles.h>
8 #include "MediaFilePlayer.h"
9 #include "ObjectList.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 BObjectList<MediaFilePlayer> list;
15 
16 MediaFilePlayer *
17 FindMediaFilePlayer(MediaFilePlayer *player, void *media_name)
18 {
19 	if (!strcmp(player->Name(), (const char *)media_name))
20 		return player;
21 	return NULL;
22 }
23 
24 
25 void
26 PlayMediaFile(const char *media_type, const char *media_name)
27 {
28 	entry_ref ref;
29 	if (BMediaFiles().GetRefFor(media_type, media_name, &ref)!=B_OK
30 		|| !BEntry(&ref).Exists())
31 		return;
32 
33 	MediaFilePlayer *player = list.EachElement(FindMediaFilePlayer, (void *)media_name);
34 	if (player) {
35 		if (*(player->Ref()) == ref) {
36 			player->Restart();
37 			return;
38 		}
39 
40 		list.RemoveItem(player);
41 		delete player;
42 		player = NULL;
43 	}
44 
45 	if (!player) {
46 		player = new MediaFilePlayer(media_type, media_name, &ref);
47 		if (player->InitCheck() == B_OK)
48 			list.AddItem(player);
49 		else
50 			delete player;
51 	}
52 }
53 
54 
55 
56 MediaFilePlayer::MediaFilePlayer(const char *media_type,
57 	const char *media_name, entry_ref *ref) :
58 	fInitCheck(B_ERROR),
59 	fRef(*ref),
60 	fSoundPlayer(NULL),
61 	fPlayTrack(NULL)
62 {
63 	fName = strdup(media_name);
64 
65 	fPlayFile = new BMediaFile(&fRef);
66 	if ((fInitCheck = fPlayFile->InitCheck()) <B_OK) {
67 		return;
68 	}
69 
70 	memset(&fPlayFormat, 0, sizeof(fPlayFormat));
71 
72 	for (int i=0; i < fPlayFile->CountTracks(); i++) {
73 		BMediaTrack *track = fPlayFile->TrackAt(i);
74 		if (track == NULL)
75 			continue;
76 		fPlayFormat.type = B_MEDIA_RAW_AUDIO;
77 		fPlayFormat.u.raw_audio.buffer_size = 256;
78 		if ((track->DecodedFormat(&fPlayFormat) == B_OK)
79 			&& (fPlayFormat.type == B_MEDIA_RAW_AUDIO)) {
80 			fPlayTrack = track;
81 			break;
82 		}
83 		fPlayFile->ReleaseTrack(track);
84 	}
85 
86 	if (fPlayTrack == NULL) {
87 		fInitCheck = B_BAD_VALUE;
88 		return;
89 	}
90 
91 	fSoundPlayer = new BSoundPlayer(&fPlayFormat.u.raw_audio, media_name, PlayFunction,
92 		NULL, this);
93 	if ((fInitCheck = fSoundPlayer->InitCheck()) != B_OK) {
94 		return;
95 	}
96 
97 	fSoundPlayer->SetVolume(1.0f);
98 	fSoundPlayer->SetHasData(true);
99 	fSoundPlayer->Start();
100 }
101 
102 
103 MediaFilePlayer::~MediaFilePlayer()
104 {
105 	delete fSoundPlayer;
106 	delete fPlayFile;
107 	free(fName);
108 }
109 
110 
111 status_t
112 MediaFilePlayer::InitCheck()
113 {
114 	return fInitCheck;
115 }
116 
117 
118 bool
119 MediaFilePlayer::IsPlaying()
120 {
121 	return (fSoundPlayer && fSoundPlayer->HasData());
122 }
123 
124 void
125 MediaFilePlayer::Restart()
126 {
127 	fSoundPlayer->Stop();
128 	int64 frame = 0;
129 	fPlayTrack->SeekToFrame(&frame);
130 	fSoundPlayer->SetHasData(true);
131 	fSoundPlayer->Start();
132 }
133 
134 
135 void
136 MediaFilePlayer::Stop()
137 {
138 	fSoundPlayer->Stop();
139 }
140 
141 
142 void
143 MediaFilePlayer::PlayFunction(void *cookie, void * buffer, size_t size, const media_raw_audio_format & format)
144 {
145 	MediaFilePlayer *player = (MediaFilePlayer *)cookie;
146 	int64 frames = 0;
147 	player->fPlayTrack->ReadFrames(buffer, &frames);
148 
149 	if (frames <=0) {
150 		player->fSoundPlayer->SetHasData(false);
151 	}
152 }
153