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