]> Joshua Wise's Git repositories - patchfork.git/blob - jorbis/src/JOrbisPlayer.java
initial import from pitchfork-0.5.5
[patchfork.git] / jorbis / src / JOrbisPlayer.java
1 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2 /* JOrbisPlayer -- pure Java Ogg Vorbis player
3  *
4  * Copyright (C) 2000 ymnk, JCraft,Inc.
5  *
6  * Written by: 2000 ymnk<ymnk@jcraft.com>
7  *
8  * Many thanks to 
9  *   Monty <monty@xiph.org> and 
10  *   The XIPHOPHORUS Company http://www.xiph.org/ .
11  * JOrbis has been based on their awesome works, Vorbis codec and
12  * JOrbisPlayer depends on JOrbis.
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  */
28
29 /*
30  * Modified 2007 by Roger Bystrøm for pitchfork <pitchfork@remiss.org>
31  */
32
33 import java.util.*;
34 import java.io.BufferedReader;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.net.*;
38
39 import java.awt.*;
40 import java.awt.event.*;
41 import java.applet.*;
42 import javax.swing.*;
43
44 import com.jcraft.jorbis.*;
45 import com.jcraft.jogg.*;
46
47 import javax.sound.sampled.*;
48
49 public class JOrbisPlayer extends JApplet implements ActionListener {
50
51         Thread player=null;
52         InputStream bitStream=null;
53         URLConnection urlc = null;
54
55         public static final String PLAY = "Play", STOP = "Stop";
56         
57         static AppletContext acontext=null;
58
59         static final int BUFSIZE=4096*2;
60         static int convsize=BUFSIZE*2;
61         static byte[] convbuffer=new byte[convsize]; 
62
63         PlayWatch playThread;
64         
65         private int RETRY=3;
66         int retry=RETRY;
67
68         SyncState oy;
69         StreamState os;
70         Page og;
71         Packet op;
72         Info vi;
73         Comment vc;
74         DspState vd;
75         Block vb;
76
77         byte[] buffer=null;
78         int bytes=0;
79
80         int format;
81         int rate=0;
82         int channels=0;
83         int left_vol_scale=100;
84         int right_vol_scale=100;
85         SourceDataLine outputLine=null;
86         String current_source=null;
87
88         int frameSizeInBytes;
89         int bufferLengthInBytes;
90
91         boolean playonstartup=false;
92
93         public Color bgColor = Color.lightGray;
94
95         public void init(){
96
97                 playThread = new PlayWatch();
98                 playThread.start();
99
100                 acontext=getAppletContext();
101
102                 loadPlaylist();
103
104                 if(playlist.size()>0){
105                         String s=getParameter("jorbis.player.playonstartup");
106                         if(s!=null && s.equals("yes"))
107                                 playonstartup=true; 
108                 }
109
110                 String c = getParameter("jorbis.player.bgcolor");
111
112                 try {
113                         bgColor = new Color(Integer.parseInt(c));
114                 } catch (Exception e) {}
115
116                 System.out.println("Bg-color: specified: " +c + ", using: " +  bgColor.toString());
117
118                 initUI();
119
120                 getContentPane().setLayout(new BorderLayout());
121                 getContentPane().add(panel);
122                 setBackground(bgColor);
123                 repaint();
124
125         }
126
127         public void start(){
128                 super.start();
129                 if(playonstartup){
130                         play_sound(); 
131                 }
132         }    
133
134         void init_jorbis(){
135                 oy=new SyncState();
136                 os=new StreamState();
137                 og=new Page();
138                 op=new Packet();
139
140                 vi=new Info();
141                 vc=new Comment();
142                 vd=new DspState();
143                 vb=new Block(vd);
144
145                 buffer=null;
146                 bytes=0;
147
148                 oy.init();
149         }
150
151         public void closeOutputLine() {
152                 if(outputLine!=null){
153                         //outputLine.drain();
154                         outputLine.stop();
155                         outputLine.flush();
156                         outputLine.close();
157                         outputLine = null;
158                 }
159         }
160
161         public void closeBitStream() {
162                 if(bitStream!=null) {
163                         try {
164                                 bitStream.close();
165                         } catch(Exception ee) {}
166                 }
167         }
168
169         SourceDataLine getOutputLine(int channels, int rate) throws Exception {
170                 if(outputLine==null || this.rate!=rate || this.channels!=channels){
171                         closeOutputLine();
172                         init_audio(channels, rate);
173                         outputLine.start();
174                 }
175                 return outputLine;
176         }
177
178         void init_audio(int channels, int rate) throws Exception {
179                 try {
180
181                         AudioFormat audioFormat = 
182                                 new AudioFormat((float)rate, 
183                                                 16,
184                                                 channels,
185                                                 true,  // PCM_Signed
186                                                 false  // littleEndian
187                                 );
188                         DataLine.Info info = 
189                                 new DataLine.Info(SourceDataLine.class,
190                                                 audioFormat, 
191                                                 AudioSystem.NOT_SPECIFIED);
192                         if (!AudioSystem.isLineSupported(info)) {
193                                 //System.out.println("Line " + info + " not supported.");
194                                 return;
195                         }
196
197                         try{
198                                 outputLine = (SourceDataLine) AudioSystem.getLine(info);
199                                 //outputLine.addLineListener(this);
200                                 outputLine.open(audioFormat);
201                         } catch (LineUnavailableException ex) { 
202                                 System.out.println("Unable to open the sourceDataLine: " + ex);
203                                 if(acontext != null)
204                                         acontext.showStatus("Streaming applet: unable to open output device");
205                                 throw ex;
206                         } 
207
208                         frameSizeInBytes = audioFormat.getFrameSize();
209                         int bufferLengthInFrames = outputLine.getBufferSize()/frameSizeInBytes/2;
210                         bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
211
212                         this.rate=rate;
213                         this.channels=channels;
214                 }
215                 catch(Exception ee){
216                         System.out.println(ee);
217                         closeOutputLine();
218                         throw ee;
219                 }
220         }
221         
222         private void play_stream(Thread me) {
223
224                 boolean chained=false;
225
226                 init_jorbis();
227
228                 retry=RETRY;
229
230                 loop:
231                         while(true){
232                                 int eos=0;
233
234                                 int index=oy.buffer(BUFSIZE);
235                                 buffer=oy.data;
236                                 try{ 
237                                         bytes=bitStream.read(buffer, index, BUFSIZE); 
238                                 }
239                                 catch(Exception e){
240                                         System.err.println(e);
241                                         return;
242                                 }
243                                 oy.wrote(bytes);
244
245                                 if(chained){
246                                         chained=false;
247                                 }
248                                 else {
249                                         if(oy.pageout(og)!=1){
250                                                 if(bytes<BUFSIZE)break;
251                                                 System.err.println("Input does not appear to be an Ogg bitstream.");
252                                                 return;
253                                         }
254                                 }
255                                 os.init(og.serialno());
256                                 os.reset();
257
258                                 vi.init();
259                                 vc.init();
260
261                                 if(os.pagein(og)<0){ 
262                                         // error; stream version mismatch perhaps
263                                         System.err.println("Error reading first page of Ogg bitstream data.");
264                                         return;
265                                 }
266
267                                 retry=RETRY;
268
269                                 if(os.packetout(op)!=1){ 
270                                         // no page? must not be vorbis
271                                         System.err.println("Error reading initial header packet.");
272                                         break;
273                                 }
274
275                                 if(vi.synthesis_headerin(vc, op)<0){ 
276                                         // error case; not a vorbis header
277                                         System.err.println("This Ogg bitstream does not contain Vorbis audio data.");
278                                         return;
279                                 }
280
281                                 int i=0;
282
283                                 while(i<2){
284                                         while(i<2){
285                                                 int result=oy.pageout(og);
286                                                 if(result==0) break; // Need more data
287                                                 if(result==1){
288                                                         os.pagein(og);
289                                                         while(i<2){
290                                                                 result=os.packetout(op);
291                                                                 if(result==0)break;
292                                                                 if(result==-1){
293                                                                         System.err.println("Corrupt secondary header.  Exiting.");
294                                                                         //return;
295                                                                         break loop;
296                                                                 }
297                                                                 vi.synthesis_headerin(vc, op);
298                                                                 i++;
299                                                         }
300                                                 }
301                                         }
302
303                                         index=oy.buffer(BUFSIZE);
304                                         buffer=oy.data; 
305                                         try{ bytes=bitStream.read(buffer, index, BUFSIZE); }
306                                         catch(Exception e){
307                                                 System.err.println(e);
308                                                 return;
309                                         }
310                                         if(bytes==0 && i<2){
311                                                 System.err.println("End of file before finding all Vorbis headers!");
312                                                 return;
313                                         }
314                                         oy.wrote(bytes);
315                                 }
316
317                                 {
318                                         byte[][] ptr=vc.user_comments;
319                                         StringBuffer sb=null;
320                                         if(acontext!=null) sb=new StringBuffer();
321                                         String artist = null, title = null, album = null, tmp;
322                                         for(int j=0; j<ptr.length;j++){
323                                                 if(ptr[j]==null) break;
324                                                 tmp = new String(ptr[j], 0, ptr[j].length-1);
325                                                 System.err.println("Comment: "+tmp);
326                                                 if(sb!=null) {
327                                                         if(tmp.startsWith("ARTIST")) 
328                                                                 artist = new String(ptr[j], 7, ptr[j].length-8);
329                                                         else if(tmp.startsWith("TITLE"))
330                                                                 title = new String(ptr[j], 6, ptr[j].length-7);
331                                                         else if(tmp.startsWith("ALBUM"))
332                                                                 album = new String(ptr[j], 6, ptr[j].length-7);
333                                                         else
334                                                                 sb.append(" "+tmp);
335                                                 }
336                                         } 
337                                         System.err.println("Bitstream is "+vi.channels+" channel, "+vi.rate+"Hz");
338                                         System.err.println("Encoded by: "+new String(vc.vendor, 0, vc.vendor.length-1)+"\n");
339                                         if(acontext!=null) {
340                                                 StringBuffer stat = new StringBuffer();
341                                                 if(title!=null) {
342                                                         stat.append(title);
343                                                         if(album!=null) {
344                                                                 stat.append(" on ");
345                                                                 stat.append(album);
346                                                         }
347
348                                                 }
349                                                 else if(album!=null){ // hmm
350                                                         stat.append("Album ");
351                                                         stat.append(album);
352                                                 }
353                                                 
354                                                 if(artist!=null) {
355                                                         stat.append(" by ");
356                                                         stat.append(artist);
357                                                 }
358                                                 
359                                                 if(sb.length()>0)
360                                                         stat.append(" " +sb);
361                                                 acontext.showStatus(stat.toString());
362                                         }
363                                 }
364
365                                 convsize=BUFSIZE/vi.channels;
366
367                                 vd.synthesis_init(vi);
368                                 vb.init(vd);
369
370                                 float[][][] _pcmf=new float[1][][];
371                                 int[] _index=new int[vi.channels];
372
373                                 try {
374                                         getOutputLine(vi.channels, vi.rate);
375                                 } catch(Exception e) {
376                                         stop_sound();
377                                         return;
378                                 }
379
380                                 while(eos==0){
381                                         while(eos==0){
382
383                                                 if(player!=me){
384                                                         System.err.println("player!=me bye.");
385                                                         closeBitStream();
386                                                         closeOutputLine();
387                                                         if(acontext!=null)
388                                                                 acontext.showStatus("");
389                                                         return;
390                                                 }
391
392                                                 int result=oy.pageout(og);
393                                                 if(result==0)break; // need more data
394                                                 if(result==-1){ // missing or corrupt data at this page position
395                                                         //System.err.println("Corrupt or missing data in bitstream; continuing...");
396                                                 }
397                                                 else{
398                                                         os.pagein(og);
399
400                                                         if(og.granulepos()==0){  //
401                                                                 chained=true;          //
402                                                                 eos=1;                 // 
403                                                                 break;                 //
404                                                         }                        //
405
406                                                         while(true){
407                                                                 result=os.packetout(op);
408                                                                 if(result==0)break; // need more data
409                                                                 if(result==-1){ 
410                                                                         // missing or corrupt data at this page position
411                                                                 }
412                                                                 else{
413                                                                         // we have a packet.  Decode it
414                                                                         int samples;
415                                                                         if(vb.synthesis(op)==0){ // test for success!
416                                                                                 vd.synthesis_blockin(vb);
417                                                                         }
418                                                                         while((samples=vd.synthesis_pcmout(_pcmf, _index))>0){
419                                                                                 float[][] pcmf=_pcmf[0];
420                                                                                 int bout=(samples<convsize?samples:convsize);
421
422                                                                                 // convert doubles to 16 bit signed ints (host order) and
423                                                                                 // interleave
424                                                                                 for(i=0;i<vi.channels;i++){
425                                                                                         int ptr=i*2;
426                                                                                         //int ptr=i;
427                                                                                         int mono=_index[i];
428                                                                                         for(int j=0;j<bout;j++){
429                                                                                                 int val=(int)(pcmf[i][mono+j]*32767.);
430                                                                                                 if(val>32767){
431                                                                                                         val=32767;
432                                                                                                 }
433                                                                                                 if(val<-32768){
434                                                                                                         val=-32768;
435                                                                                                 }
436                                                                                                 if(val<0) val=val|0x8000;
437                                                                                                 convbuffer[ptr]=(byte)(val);
438                                                                                                 convbuffer[ptr+1]=(byte)(val>>>8);
439                                                                                                 ptr+=2*(vi.channels);
440                                                                                         }
441                                                                                 }
442                                                                                 outputLine.write(convbuffer, 0, 2*vi.channels*bout);
443                                                                                 vd.synthesis_read(bout);
444                                                                         }         
445                                                                 }
446                                                         }
447                                                         if(og.eos()!=0)eos=1;
448                                                 }
449                                         }
450
451                                         if(eos==0){
452                                                 index=oy.buffer(BUFSIZE);
453                                                 buffer=oy.data;
454                                                 try{ bytes=bitStream.read(buffer,index,BUFSIZE); }
455                                                 catch(Exception e){
456                                                         System.err.println(e);
457                                                         closeOutputLine();
458                                                         return;
459                                                 }
460                                                 if(bytes==-1){
461                                                         break;
462                                                 }
463                                                 oy.wrote(bytes);
464                                                 if(bytes==0)eos=1;
465                                         }
466                                 }
467
468                                 os.clear();
469                                 vb.clear();
470                                 vd.clear();
471                                 vi.clear();
472                         }
473
474                 closeOutputLine();
475                 oy.clear();
476                 if(acontext!=null)
477                         acontext.showStatus("");
478
479                 closeBitStream();
480         }
481
482         public void stop(){
483                 if(player==null){
484                         closeOutputLine();
485                         closeBitStream();
486                 }
487                 player=null;
488         }
489
490         Vector playlist=new Vector();
491
492         public void actionPerformed(ActionEvent e){
493                 String command=((JButton)(e.getSource())).getText();
494                 if(command.equals(PLAY) && player==null){ 
495                         play_sound();
496                 }
497                 else if(player!=null){
498                         stop_sound();
499                 }
500         }
501         
502         private void playFromOwnThread() {
503                 synchronized(playThread) {
504                         playThread.notify();
505                 }
506         }
507
508         private void playFromThisThread() {
509                 if(player!=null) 
510                         return;
511                 /*player=new Thread(this);
512                 player.start();*/
513                 // todo
514                 start_button.setText(STOP); 
515                 String item=getShoutSource();
516                 if(item==null) {
517                         stop_sound();
518                         return;
519                 }
520                 bitStream=selectSource(item);
521                 player = Thread.currentThread();
522                 if(bitStream!=null){
523                         play_stream(player);
524                 }
525                 else System.out.println("Bitstream is null");
526                 bitStream=null;
527                 
528                 stop_sound();
529         }
530
531
532         /* hooks */
533
534         public boolean isPlaying() {
535                 return player != null;
536         }
537
538         public void play_sound(){
539                 playFromOwnThread();
540         }
541
542         public void stop_sound(){
543                 player=null;
544                 start_button.setText(PLAY);
545
546         }
547         
548         InputStream selectSource(String item){
549                 if(item.endsWith(".pls")){
550                         item=fetch_pls(item);
551                         if(item==null) return null;
552                         //System.out.println("fetch: "+item);
553                 }
554                 else if(item.endsWith(".m3u")){
555                         item=fetch_m3u(item);
556                         if(item==null)return null;
557                         //System.out.println("fetch: "+item);
558                 }
559
560                 if(!item.endsWith(".ogg")){
561                         return null;  
562                 }
563
564                 InputStream is=null;
565                 URLConnection urlc=null;
566                 try{
567                         URL url=null;
568                         url=new URL(getCodeBase(), item);
569                         urlc=url.openConnection();
570                         urlc.setRequestProperty("Pragma", "no-cache");
571                         urlc.setUseCaches(false);
572                         is=urlc.getInputStream();
573                         current_source=url.getProtocol()+"://"+url.getHost()+":"+url.getPort()+url.getFile();
574                 }
575                 catch(Exception ee){
576                         System.err.println(ee);             
577                 }
578
579                 if(is==null) {
580                         System.out.println("Selected input stream is null");
581                         return null;
582                 }
583
584                 System.out.println("Select: "+item);
585                 return is;
586         }
587
588         String fetch_pls(String pls){
589                 InputStream pstream=null;
590                 if(pls.startsWith("http://")){
591                         try{
592                                 URL url=null;
593                                 url=new URL(getCodeBase(), pls);
594                                  urlc=url.openConnection();
595                                 pstream=urlc.getInputStream();
596                         }
597                         catch(Exception ee){
598                                 System.err.println(ee);             
599                                 return null;
600                         }
601                 }
602
603                 String line=null;
604                 while(true){
605                         try{line=readline(pstream);}catch(Exception e){}
606                         if(line==null)break;
607                         if(line.startsWith("File1=")){
608                                 byte[] foo=line.getBytes();
609                                 int i=6;
610                                 for(;i<foo.length; i++){
611                                         if(foo[i]==0x0d)break;
612                                 }
613                                 return line.substring(6, i);
614                         }
615                 }
616                 return null;
617         }
618
619         String fetch_m3u(String m3u){
620                 InputStream pstream=null;
621                 if(m3u.startsWith("http://")){
622                         try{
623                                 URL url=null;
624                                 url=new URL(getCodeBase(), m3u);
625                                 
626                                 URLConnection urlc=url.openConnection();
627                                 pstream=urlc.getInputStream();
628                         }
629                         catch(Exception ee){
630                                 System.err.println(ee);             
631                                 return null;
632                         }
633                 }
634
635                 String line=null;
636                 while(true){
637                         try{line=readline(pstream);}catch(Exception e){}
638                         if(line==null)break;
639                         return line;
640                 }
641                 return null;
642         }
643
644
645         void loadPlaylist(){
646                 String s=null;
647                 for(int i=0; i<10; i++){
648                         s=getParameter("jorbis.player.play."+i);
649                         System.out.println("Play" + i + ": " + s);
650                         if(s==null)
651                                 break;
652                         playlist.addElement(s);
653                 } 
654         }
655
656         private String readline(InputStream is) {
657                 StringBuffer rtn=new StringBuffer();
658                 int temp;
659                 do {
660                         try { 
661                                 temp=is.read();
662                         }
663                         catch(Exception e) {
664                                 return null;
665                         }
666                         if(temp==-1) 
667                                 return null;
668                         if(temp!=0 && temp!='\n')
669                                 rtn.append((char)temp);
670                 }while(temp!='\n');                                                        
671                 return(rtn.toString());
672         }
673
674         public JOrbisPlayer(){
675         }
676
677         JPanel panel;
678         JButton start_button;
679
680         void initUI(){
681                 panel=new JPanel();
682
683                 start_button=new JButton(PLAY);
684                 start_button.addActionListener(this);
685                 panel.add(start_button);
686                 panel.setBackground(bgColor);
687         }
688         
689         public String getShoutSource() {
690                 try {
691                         return (String)playlist.firstElement();
692                 }
693                 catch(NoSuchElementException e) { 
694                         return null;
695                 }
696         }
697         
698         /* since js don't have proper access right's we'll need a seperate watcher thread */
699         public class PlayWatch extends Thread {
700                 
701                 public PlayWatch() { }
702                 
703                 public void run() {
704                         while(true) {
705                                 synchronized(this) {
706                                         try {
707                                                 this.wait();
708                                         }catch (InterruptedException e) {}
709                                 }
710                                 playFromThisThread();
711                         }
712                 }
713         }
714 }
This page took 0.120685 seconds and 4 git commands to generate.