summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer3/playlist.cpp6
1 files changed, 5 insertions, 1 deletions
diff --git a/noncore/multimedia/opieplayer3/playlist.cpp b/noncore/multimedia/opieplayer3/playlist.cpp
index 6f2e668..fe2dde3 100644
--- a/noncore/multimedia/opieplayer3/playlist.cpp
+++ b/noncore/multimedia/opieplayer3/playlist.cpp
@@ -1,333 +1,337 @@
1/* 1/*
2 This file is part of the Opie Project 2 This file is part of the Opie Project
3 3
4 Copyright (c) 2002 Max Reiss <harlekin@handhelds.org> 4 Copyright (c) 2002 Max Reiss <harlekin@handhelds.org>
5 Copyright (c) 2002 L. Potter <ljp@llornkcor.com> 5 Copyright (c) 2002 L. Potter <ljp@llornkcor.com>
6 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org> 6 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
7 =. 7 =.
8 .=l. 8 .=l.
9 .>+-= 9 .>+-=
10 _;:, .> :=|. This program is free software; you can 10 _;:, .> :=|. This program is free software; you can
11.> <`_, > . <= redistribute it and/or modify it under 11.> <`_, > . <= redistribute it and/or modify it under
12:`=1 )Y*s>-.-- : the terms of the GNU General Public 12:`=1 )Y*s>-.-- : the terms of the GNU General Public
13.="- .-=="i, .._ License as published by the Free Software 13.="- .-=="i, .._ License as published by the Free Software
14 - . .-<_> .<> Foundation; either version 2 of the License, 14 - . .-<_> .<> Foundation; either version 2 of the License,
15 ._= =} : or (at your option) any later version. 15 ._= =} : or (at your option) any later version.
16 .%`+i> _;_. 16 .%`+i> _;_.
17 .i_,=:_. -<s. This program is distributed in the hope that 17 .i_,=:_. -<s. This program is distributed in the hope that
18 + . -:. = it will be useful, but WITHOUT ANY WARRANTY; 18 + . -:. = it will be useful, but WITHOUT ANY WARRANTY;
19 : .. .:, . . . without even the implied warranty of 19 : .. .:, . . . without even the implied warranty of
20 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A 20 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A
21 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU 21 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.= = ; Library General Public License for more 22..}^=.= = ; Library General Public License for more
23++= -. .` .: details. 23++= -. .` .: details.
24 : = ...= . :.=- 24 : = ...= . :.=-
25 -. .:....=;==+<; You should have received a copy of the GNU 25 -. .:....=;==+<; You should have received a copy of the GNU
26 -_. . . )=. = Library General Public License along with 26 -_. . . )=. = Library General Public License along with
27 -- :-=` this library; see the file COPYING.LIB. 27 -- :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation, 28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330, 29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA. 30 Boston, MA 02111-1307, USA.
31 31
32*/ 32*/
33#include "playlist.h" 33#include "playlist.h"
34#include "../opieplayer2/lib.h" 34#include "../opieplayer2/lib.h"
35#include "../opieplayer2/om3u.h" 35#include "../opieplayer2/om3u.h"
36 36
37#include <opie2/odebug.h> 37#include <opie2/odebug.h>
38#include <opie2/oresource.h> 38#include <opie2/oresource.h>
39#include <opie2/ofiledialog.h> 39#include <opie2/ofiledialog.h>
40 40
41#include <qpe/resource.h> 41#include <qpe/resource.h>
42 42
43#include <qfileinfo.h> 43#include <qfileinfo.h>
44#include <qmessagebox.h> 44#include <qmessagebox.h>
45#include <qdir.h> 45#include <qdir.h>
46 46
47//#define DEFAULT_FILE_TYPES "*.mp3;*.ogg;*.ogm;*.wma;*.wav;*.asf;*.au;*.avi;*.mpeg;*.mpg;*.mv1;*.mov;*.wmv;*.pls;*.m3u;*.mp4;*.m4a" 47//#define DEFAULT_FILE_TYPES "*.mp3;*.ogg;*.ogm;*.wma;*.wav;*.asf;*.au;*.avi;*.mpeg;*.mpg;*.mv1;*.mov;*.wmv;*.pls;*.m3u;*.mp4;*.m4a"
48#define DEFAULT_FILE_TYPES "*.mp3;*.ogg;*.ogm;*.wma;*.wav;*.asf;*.au;*.avi;*.mpeg;*.mpg;*.mv1;*.mov;*.wmv;*.mp4;*.m4a" 48#define DEFAULT_FILE_TYPES "*.mp3;*.ogg;*.ogm;*.wma;*.wav;*.asf;*.au;*.avi;*.mpeg;*.mpg;*.mv1;*.mov;*.wmv;*.mp4;*.m4a"
49 49
50PlaylistItem::PlaylistItem(const DocLnk& aLink,PlaylistView*parent) 50PlaylistItem::PlaylistItem(const DocLnk& aLink,PlaylistView*parent)
51 :QListViewItem(parent),m_Content(aLink),m_video(false) 51 :QListViewItem(parent),m_Content(aLink),m_video(false)
52{ 52{
53} 53}
54 54
55PlaylistItem::PlaylistItem(const DocLnk&aLink,PlaylistView*parent,PlaylistItem*after) 55PlaylistItem::PlaylistItem(const DocLnk&aLink,PlaylistView*parent,PlaylistItem*after)
56 :QListViewItem(parent,after),m_Content(aLink),m_video(false) 56 :QListViewItem(parent,after),m_Content(aLink),m_video(false)
57{ 57{
58} 58}
59 59
60void PlaylistItem::Video(bool y) 60void PlaylistItem::Video(bool y)
61{ 61{
62 m_video=y; 62 m_video=y;
63 if (m_video) { 63 if (m_video) {
64 setPixmap(0,Opie::Core::OResource::loadPixmap("opieplayer2/videofile")); 64 setPixmap(0,Opie::Core::OResource::loadPixmap("opieplayer2/videofile"));
65 } else { 65 } else {
66 setPixmap(0,Opie::Core::OResource::loadPixmap("opieplayer2/musicfile")); 66 setPixmap(0,Opie::Core::OResource::loadPixmap("opieplayer2/musicfile"));
67 } 67 }
68} 68}
69 69
70PlaylistItem::~PlaylistItem() 70PlaylistItem::~PlaylistItem()
71{ 71{
72} 72}
73 73
74/* PlaylistView Methods */ 74/* PlaylistView Methods */
75PlaylistView::PlaylistView(QWidget *parent, const char *name) 75PlaylistView::PlaylistView(QWidget *parent, const char *name)
76 : QListView(parent,name) 76 : QListView(parent,name)
77{ 77{
78// columnLabels << tr("FullName"); 78// columnLabels << tr("FullName");
79 columnLabels << tr(""); // icon 79 columnLabels << tr(""); // icon
80 columnLabels << tr("File"); 80 columnLabels << tr("File");
81 columnLabels << tr("Playtime"); 81 columnLabels << tr("Playtime");
82 columnLabels << tr("Artist"); 82 columnLabels << tr("Artist");
83 columnLabels << tr("Album"); 83 columnLabels << tr("Album");
84 columnLabels << tr("Title"); 84 columnLabels << tr("Title");
85 columnLabels << tr("Type"); 85 columnLabels << tr("Type");
86 columnLabels << tr("Size"); 86 columnLabels << tr("Size");
87 for (QStringList::Iterator it = columnLabels.begin(); it != columnLabels.end(); ++it) { 87 for (QStringList::Iterator it = columnLabels.begin(); it != columnLabels.end(); ++it) {
88 addColumn(*it); 88 addColumn(*it);
89 } 89 }
90 m_Infolib=0; 90 m_Infolib=0;
91 setAllColumnsShowFocus(true); 91 setAllColumnsShowFocus(true);
92 setSelectionMode(Single); 92 setSelectionMode(Single);
93 setSorting(-1); 93 setSorting(-1);
94 m_lastItem = 0; 94 m_lastItem = 0;
95 m_lastDir = QDir::homeDirPath(); 95 m_lastDir = QDir::homeDirPath();
96} 96}
97 97
98PlaylistView::~PlaylistView() 98PlaylistView::~PlaylistView()
99{ 99{
100 if (m_Infolib) delete m_Infolib; 100 if (m_Infolib) delete m_Infolib;
101} 101}
102 102
103void PlaylistView::checkLib() 103void PlaylistView::checkLib()
104{ 104{
105 if (!m_Infolib) { 105 if (!m_Infolib) {
106 m_Infolib = new XINE::Lib(XINE::Lib::InitializeImmediately); 106 m_Infolib = new XINE::Lib(XINE::Lib::InitializeImmediately);
107 connect(m_Infolib,SIGNAL(stopped()),this,SLOT(slotDummyStop())); 107 connect(m_Infolib,SIGNAL(stopped()),this,SLOT(slotDummyStop()));
108 m_Infolib->ensureInitialized(); 108 m_Infolib->ensureInitialized();
109 } 109 }
110} 110}
111 111
112void PlaylistView::slotDummyStop() 112void PlaylistView::slotDummyStop()
113{ 113{
114 odebug << "void PlaylistView::slotDummyStop()" << oendl; 114 odebug << "void PlaylistView::slotDummyStop()" << oendl;
115} 115}
116 116
117void PlaylistView::slotAddFile(const DocLnk&aLink) 117void PlaylistView::slotAddFile(const DocLnk&aLink)
118{ 118{
119 QFileInfo f(aLink.file()); 119 QFileInfo f(aLink.file());
120 if (f.extension(FALSE).lower()=="m3u"||f.extension(FALSE).lower()=="pls") { 120 if (f.extension(FALSE).lower()=="m3u"||f.extension(FALSE).lower()=="pls") {
121 readPlayList(aLink.file()); 121 readPlayList(aLink.file());
122 } else { 122 } else {
123 addFile(aLink.file(),aLink.name()); 123 addFile(aLink.file(),aLink.name());
124 } 124 }
125 emit contentChanged(childCount()); 125 emit contentChanged(childCount());
126} 126}
127 127
128void PlaylistView::addFile(const QString&aFile,const QString&aName) 128void PlaylistView::addFile(const QString&aFile,const QString&aName)
129{ 129{
130 QFileInfo fileInfo(aFile); 130 QFileInfo fileInfo(aFile);
131 if (!fileInfo.exists()) return; 131 if (!fileInfo.exists()) return;
132 checkLib(); 132 checkLib();
133 QString name = aName; 133 QString name = aName;
134 if (name.isEmpty()) { 134 if (name.isEmpty()) {
135 name = fileInfo.fileName(); 135 name = fileInfo.fileName();
136 } 136 }
137 int i = m_Infolib->setfile(aFile.utf8().data()); 137 int i = m_Infolib->setfile(aFile.utf8().data());
138 /* realy! otherwise we get an "stopped" signal when playing! - I don't know why */ 138 /* realy! otherwise we get an "stopped" signal when playing! - I don't know why */
139 m_Infolib->stop(); 139 m_Infolib->stop();
140 odebug << "File set: " << i << " ("<<aFile.utf8().data()<<")"<<oendl; 140 odebug << "File set: " << i << " ("<<aFile.utf8().data()<<")"<<oendl;
141 if (i<1) { 141 if (i<1) {
142 i = m_Infolib->error(); 142 i = m_Infolib->error();
143 odebug << "Errorcode: " << i << oendl; 143 odebug << "Errorcode: " << i << oendl;
144 QString msg; 144 QString msg;
145 msg = QString(tr("Error open file %1: ")).arg(name); 145 msg = QString(tr("Error open file %1: ")).arg(name);
146 switch (i) { 146 switch (i) {
147 case 1: 147 case 1:
148 msg += tr("No input plugin"); 148 msg += tr("No input plugin");
149 break; 149 break;
150 case 2: 150 case 2:
151 msg += tr("No demuxer plugin"); 151 msg += tr("No demuxer plugin");
152 break; 152 break;
153 case 3: 153 case 3:
154 msg += tr("Demuxer failed"); 154 msg += tr("Demuxer failed");
155 break; 155 break;
156 case 4: 156 case 4:
157 msg+=tr("Malformed mrl"); 157 msg+=tr("Malformed mrl");
158 break; 158 break;
159 default: 159 default:
160 msg += tr("Unknown error"); 160 msg += tr("Unknown error");
161 break; 161 break;
162 } 162 }
163 QMessageBox::warning(0,tr("Error reading fileheader"),msg); 163 QMessageBox::warning(0,tr("Error reading fileheader"),msg);
164 return; 164 return;
165 } 165 }
166 m_lastItem = m_items.last(); 166 if (m_items.count()>0) {
167 m_lastItem = m_items.last();
168 } else {
169 m_lastItem = 0;
170 }
167 PlaylistItem*_it = currentItem(); 171 PlaylistItem*_it = currentItem();
168 172
169 if (m_lastItem) { 173 if (m_lastItem) {
170 m_lastItem = new PlaylistItem(aFile,this,m_lastItem); 174 m_lastItem = new PlaylistItem(aFile,this,m_lastItem);
171 } else { 175 } else {
172 m_lastItem = new PlaylistItem(aFile,this); 176 m_lastItem = new PlaylistItem(aFile,this);
173 } 177 }
174 m_lastItem->setExpandable(false); 178 m_lastItem->setExpandable(false);
175 m_lastItem->setText(1,name); 179 m_lastItem->setText(1,name);
176 180
177 QString codec = m_Infolib->metaInfo(6); 181 QString codec = m_Infolib->metaInfo(6);
178 if (codec.isEmpty()) { 182 if (codec.isEmpty()) {
179 codec = m_Infolib->metaInfo(7); 183 codec = m_Infolib->metaInfo(7);
180 } 184 }
181 // codec 185 // codec
182 m_lastItem->setText(COL_TYPE,codec); 186 m_lastItem->setText(COL_TYPE,codec);
183 // title 187 // title
184 m_lastItem->setText(COL_TITLE,m_Infolib->metaInfo(0)); 188 m_lastItem->setText(COL_TITLE,m_Infolib->metaInfo(0));
185 // artist 189 // artist
186 m_lastItem->setText(COL_ARTIST,m_Infolib->metaInfo(2)); 190 m_lastItem->setText(COL_ARTIST,m_Infolib->metaInfo(2));
187 // album 191 // album
188 m_lastItem->setText(COL_ALBUM,m_Infolib->metaInfo(4)); 192 m_lastItem->setText(COL_ALBUM,m_Infolib->metaInfo(4));
189 int l = m_Infolib->length(); 193 int l = m_Infolib->length();
190 int h = l/3600; 194 int h = l/3600;
191 l-=h*3600; 195 l-=h*3600;
192 int m = l/60; 196 int m = l/60;
193 l-=m*60; 197 l-=m*60;
194 codec = ""; 198 codec = "";
195 if (h>0) { 199 if (h>0) {
196 codec.sprintf("%2i:%2i:%2i h",h,m,l); 200 codec.sprintf("%2i:%2i:%2i h",h,m,l);
197 } else { 201 } else {
198 codec.sprintf("%02i:%02i m",m,l); 202 codec.sprintf("%02i:%02i m",m,l);
199 } 203 }
200 // time 204 // time
201 m_lastItem->setText(COL_TIME,codec); 205 m_lastItem->setText(COL_TIME,codec);
202 m_lastItem->Video(m_Infolib->hasVideo()); 206 m_lastItem->Video(m_Infolib->hasVideo());
203 m_items.append(m_lastItem); 207 m_items.append(m_lastItem);
204 if (_it==NULL) { 208 if (_it==NULL) {
205 setSelected(m_lastItem,true); 209 setSelected(m_lastItem,true);
206 } 210 }
207} 211}
208 212
209void PlaylistView::slotAppendDir() 213void PlaylistView::slotAppendDir()
210{ 214{
211 QString _dir = Opie::Ui::OFileDialog::getDirectory(Opie::Ui::OFileSelector::Extended,m_lastDir,0,m_lastDir); 215 QString _dir = Opie::Ui::OFileDialog::getDirectory(Opie::Ui::OFileSelector::Extended,m_lastDir,0,m_lastDir);
212 if (_dir.isEmpty()) return; 216 if (_dir.isEmpty()) return;
213 m_lastDir = _dir; 217 m_lastDir = _dir;
214 QDir sDir(_dir); 218 QDir sDir(_dir);
215 QStringList list = sDir.entryList(DEFAULT_FILE_TYPES,QDir::Files,QDir::Name | QDir::IgnoreCase); 219 QStringList list = sDir.entryList(DEFAULT_FILE_TYPES,QDir::Files,QDir::Name | QDir::IgnoreCase);
216 for (unsigned i = 0; i < list.count();++i) { 220 for (unsigned i = 0; i < list.count();++i) {
217 addFile(_dir+QString("/")+list[i]); 221 addFile(_dir+QString("/")+list[i]);
218 } 222 }
219 emit contentChanged(childCount()); 223 emit contentChanged(childCount());
220} 224}
221 225
222void PlaylistView::slotOpenM3u() 226void PlaylistView::slotOpenM3u()
223{ 227{
224 QStringList types; 228 QStringList types;
225 QMap<QString, QStringList> mimeTypes; 229 QMap<QString, QStringList> mimeTypes;
226 types << "audio/x-mpegurl"; 230 types << "audio/x-mpegurl";
227 mimeTypes.insert("Playlists",types); 231 mimeTypes.insert("Playlists",types);
228// mimeTypes.insert("All",types); 232// mimeTypes.insert("All",types);
229 QString fileName= Opie::Ui::OFileDialog::getOpenFileName(Opie::Ui::OFileSelector::EXTENDED, 233 QString fileName= Opie::Ui::OFileDialog::getOpenFileName(Opie::Ui::OFileSelector::EXTENDED,
230 m_lastDir,"playlist.m3u", mimeTypes); 234 m_lastDir,"playlist.m3u", mimeTypes);
231 if (fileName.isEmpty()) { 235 if (fileName.isEmpty()) {
232 return; 236 return;
233 } 237 }
234 readPlayList(fileName); 238 readPlayList(fileName);
235 emit contentChanged(childCount()); 239 emit contentChanged(childCount());
236} 240}
237 241
238void PlaylistView::readPlayList(const QString&fileName) 242void PlaylistView::readPlayList(const QString&fileName)
239{ 243{
240 QFileInfo f(fileName); 244 QFileInfo f(fileName);
241 245
242 Om3u _om3u(fileName, IO_ReadOnly); 246 Om3u _om3u(fileName, IO_ReadOnly);
243 if (f.extension(FALSE).lower()=="m3u") { 247 if (f.extension(FALSE).lower()=="m3u") {
244 _om3u.readM3u(); 248 _om3u.readM3u();
245 } else if (f.extension(FALSE).lower()=="pls") { 249 } else if (f.extension(FALSE).lower()=="pls") {
246 _om3u.readPls(); 250 _om3u.readPls();
247 } 251 }
248 for (unsigned int j=0; j<_om3u.count();++j) { 252 for (unsigned int j=0; j<_om3u.count();++j) {
249 addFile(_om3u[j]); 253 addFile(_om3u[j]);
250 } 254 }
251} 255}
252 256
253void PlaylistView::slotSaveAsM3u() 257void PlaylistView::slotSaveAsM3u()
254{ 258{
255 QStringList types; 259 QStringList types;
256 QMap<QString, QStringList> mimeTypes; 260 QMap<QString, QStringList> mimeTypes;
257 types << "audio/x-mpegurl"; 261 types << "audio/x-mpegurl";
258 mimeTypes.insert("Playlists",types); 262 mimeTypes.insert("Playlists",types);
259 QString fileName= Opie::Ui::OFileDialog::getSaveFileName(Opie::Ui::OFileSelector::EXTENDED, 263 QString fileName= Opie::Ui::OFileDialog::getSaveFileName(Opie::Ui::OFileSelector::EXTENDED,
260 m_lastDir,"playlist.m3u", mimeTypes); 264 m_lastDir,"playlist.m3u", mimeTypes);
261 odebug << "Save as " << fileName << oendl; 265 odebug << "Save as " << fileName << oendl;
262 if (fileName.isEmpty()) { 266 if (fileName.isEmpty()) {
263 return; 267 return;
264 } 268 }
265 Om3u _om3u(fileName, IO_ReadWrite | IO_Truncate); 269 Om3u _om3u(fileName, IO_ReadWrite | IO_Truncate);
266 for (unsigned j=0; j<m_items.count();++j) { 270 for (unsigned j=0; j<m_items.count();++j) {
267 _om3u.add(m_items[j]->Lnk().file()); 271 _om3u.add(m_items[j]->Lnk().file());
268 } 272 }
269 _om3u.write(); 273 _om3u.write();
270} 274}
271 275
272void PlaylistView::removeFromList(PlaylistItem*Item) 276void PlaylistView::removeFromList(PlaylistItem*Item)
273{ 277{
274 if (!Item)return; 278 if (!Item)return;
275 t_itemlist::Iterator iter,it2; 279 t_itemlist::Iterator iter,it2;
276 iter = m_items.find(Item); 280 iter = m_items.find(Item);
277 it2 = m_items.end(); 281 it2 = m_items.end();
278 if (iter!=m_items.end()) { 282 if (iter!=m_items.end()) {
279 it2 = iter; 283 it2 = iter;
280 ++it2; 284 ++it2;
281 m_items.remove(iter); 285 m_items.remove(iter);
282 } 286 }
283 delete Item; 287 delete Item;
284 if (it2!=m_items.end()) { 288 if (it2!=m_items.end()) {
285 setSelected((*it2),true); 289 setSelected((*it2),true);
286 } else if (m_items.count()) { 290 } else if (m_items.count()) {
287 QListViewItem * it = m_items.last(); 291 QListViewItem * it = m_items.last();
288 setSelected(it,true); 292 setSelected(it,true);
289 } 293 }
290 emit contentChanged(childCount()); 294 emit contentChanged(childCount());
291} 295}
292 296
293XINE::Lib*PlaylistView::getXine() 297XINE::Lib*PlaylistView::getXine()
294{ 298{
295 checkLib(); 299 checkLib();
296 return m_Infolib; 300 return m_Infolib;
297} 301}
298 302
299void PlaylistView::setCurrentItem(PlaylistItem*aItem) 303void PlaylistView::setCurrentItem(PlaylistItem*aItem)
300{ 304{
301 setSelected(aItem,true); 305 setSelected(aItem,true);
302} 306}
303 307
304PlaylistItem* PlaylistView::currentItem()const 308PlaylistItem* PlaylistView::currentItem()const
305{ 309{
306 QListViewItem*it = selectedItem(); 310 QListViewItem*it = selectedItem();
307 if (!it) return 0; 311 if (!it) return 0;
308 return (PlaylistItem*)it; 312 return (PlaylistItem*)it;
309} 313}
310 314
311PlaylistItem* PlaylistView::nextItem(PlaylistItem*parent)const 315PlaylistItem* PlaylistView::nextItem(PlaylistItem*parent)const
312{ 316{
313 if (m_items.count()==0) return 0; 317 if (m_items.count()==0) return 0;
314 if (!parent) return m_items[0]; 318 if (!parent) return m_items[0];
315 for (unsigned j=0; j<m_items.count()-1;++j) { 319 for (unsigned j=0; j<m_items.count()-1;++j) {
316 if (m_items[j]==parent) { 320 if (m_items[j]==parent) {
317 return m_items[j+1]; 321 return m_items[j+1];
318 } 322 }
319 } 323 }
320 return 0; 324 return 0;
321} 325}
322 326
323PlaylistItem* PlaylistView::prevItem(PlaylistItem*parent)const 327PlaylistItem* PlaylistView::prevItem(PlaylistItem*parent)const
324{ 328{
325 if (m_items.count()==0) return 0; 329 if (m_items.count()==0) return 0;
326 if (!parent) return m_items[m_items.count()-1]; 330 if (!parent) return m_items[m_items.count()-1];
327 for (unsigned j=m_items.count()-1; j>0;--j) { 331 for (unsigned j=m_items.count()-1; j>0;--j) {
328 if (m_items[j]==parent) { 332 if (m_items[j]==parent) {
329 return m_items[j-1]; 333 return m_items[j-1];
330 } 334 }
331 } 335 }
332 return 0; 336 return 0;
333} 337}