Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using Un4seen.Bass;
- using Un4seen.Bass.AddOn.Tags;
- using System.Runtime.InteropServices;
- // NISTON Portable Streaming Audio Player for Windows Unix and, perhaps Mac OSX
- //
- // A practical example on cross-platform development or how to use the
- // BASS Audio Library via BASS.NET under mono on ARM6 Linux.
- // This works on a Raspberry Pi! =)
- //
- // Homepage: http://niston.wordpress.com
- //
- // BASS.NET API: http://bass.radio42.com/
- // BASS for ARM Linux: http://www.un4seen.com/forum/?topic=13804.msg95617#msg95617
- namespace sndchk
- {
- class Program
- {
- // some global variables for SYNCing (not working yet, but doesn't really matter)
- static SYNCPROC _mySync;
- static SYNCPROC _StallProc;
- // some strings for the bar graph displays
- static string barBckg = "---------|---------|---------|---------|---------";
- static string barScale = "|0 20| 40| 60| 80| 100|";
- // true if we have floating point channel support from BASS, will always be false on ARM
- static bool flpSupport = true;
- static void Main(string[] args)
- {
- // clear the console and write application title
- Console.Clear();
- Console.Write("NISTON Experimental Stream Player");
- // Setup BASS Audio Lib
- SetupBassLibrary();
- // check float
- flpSupport = CheckFloatSupport();
- // init BASS using the default output device
- if (Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero))
- {
- if (flpSupport) { Console.Write(" (32bit DSP)"); }
- // check for command line arguments supplied
- if (args.Length == 0)
- {
- // add line feed and empty line
- Console.WriteLine();
- Console.WriteLine();
- // see if we are running on wintendo
- if (System.Environment.OSVersion.Platform.ToString().ToUpper().Contains("WIN32NT"))
- {
- // mono not required on windows
- Console.WriteLine("usage: sndchk.exe <Shoutcast URL>");
- }
- else
- {
- // mono required on other platforms
- Console.WriteLine("usage: mono sndchk.exe <Shoutcast URL>");
- }
- // additional line feed
- Console.SetCursorPosition(0, 17);
- // terminate
- System.Environment.Exit(1);
- }
- // get url from args
- string url = args[0];
- // show status
- Console.SetCursorPosition(67, 0);
- Console.Write("Connecting...");
- // show URL line
- Console.SetCursorPosition(0, 3);
- Console.Write(" URL : " + url);
- // attempt to create stream from URL, use SAMPLE_FLOAT if system is capable
- int stream = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_STREAM_STATUS | BASSFlag.BASS_STREAM_BLOCK | (flpSupport ? BASSFlag.BASS_SAMPLE_FLOAT : 0), null, System.IntPtr.Zero);
- Console.SetCursorPosition(67, 0);
- Console.Write(" Connected.");
- if (stream != 0)
- {
- // stream created, set SYNCs (it appears that SYNCs don't work in console application?)
- _mySync = new SYNCPROC(MetaSync);
- var res = Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero);
- _StallProc = new SYNCPROC(StallSync);
- Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_STALL, 0, _StallProc, IntPtr.Zero);
- // play the stream channel
- Bass.BASS_ChannelPlay(stream, false);
- }
- else
- {
- // error creating the stream, print message and terminate
- Bass.BASS_Free();
- Console.WriteLine("Stream error: {0}", Bass.BASS_ErrorGetCode());
- System.Environment.Exit(1);
- }
- // playing now, so show Exit Hint.
- Console.SetCursorPosition(58, 0);
- Console.Write("Press any key to quit.");
- // hide cursor
- Console.CursorVisible = false;
- // main loop until key press
- while (!Console.KeyAvailable)
- {
- // check for stream EOF
- if (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_STOPPED)
- {
- // free ended stream / BASS library
- Bass.BASS_StreamFree(stream);
- Bass.BASS_Free();
- // clear status info
- // playing now, so show Exit Hint.
- // show goodbye message
- Console.SetCursorPosition(58, 0);
- Console.Write(" Stream has ended.");
- Console.SetCursorPosition(0, 17);
- Console.CursorVisible = true;
- // terminate
- System.Environment.Exit(0);
- }
- // read stream information.........................................................
- // get channel information
- BASS_CHANNELINFO chanInf = Bass.BASS_ChannelGetInfo(stream);
- // determine channel bits
- int chanBits = 16;
- if (chanInf != null)
- {
- // get chanel bits
- if (chanInf.Is32bit) { chanBits = 32; }
- if (chanInf.Is8bit) { chanBits = 8; }
- }
- // get audio levels
- int level = Bass.BASS_ChannelGetLevel(stream);
- int left = Utils.LowWord32(level);
- int right = Utils.HighWord32(level);
- // get buffer level
- long len = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_END);
- long down = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_DOWNLOAD);
- long dec = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_CURRENT);
- int progress = (int)(Math.Floor(((float)(down) - (float)(dec)) * (float)(100) / (float)(len)));
- if (progress > 100) { progress = 100; }; if (progress < 0) { progress = 0; }
- // get tags
- TAG_INFO myTags = new TAG_INFO();
- var tags = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_META);
- if (tags != null) { myTags.UpdateFromMETA(tags, true, true); }
- // check http info
- var httpInfo = Bass.BASS_ChannelGetTagsHTTP(stream);
- var httpInfo2 = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_HTTP);
- // get station and bitrate from ICY tags
- string bitRate = "";
- string stationName = "NO INFORMATION";
- string[] icyInfo = Bass.BASS_ChannelGetTagsICY(stream);
- if (icyInfo != null)
- {
- for (int n = 0; n <= icyInfo.GetUpperBound(0); n++)
- {
- // debug.print all ICY tags to output window
- System.Diagnostics.Debug.Print("ICY_TAG[" + n + "] : " + icyInfo[n]);
- // found bit rate
- if (icyInfo[n].Contains("icy-br")) { bitRate = icyInfo[n].Replace("icy-br:", ""); }
- // found station name
- if (icyInfo[n].Contains("icy-name")) { stationName = icyInfo[n].Replace("icy-name:", ""); }
- }
- }
- // update display..................................................................
- // home cursor
- Console.SetCursorPosition(0, 5);
- // write station name
- Console.WriteLine(" Station : " + stationName);
- // write song information (artist, title)
- Console.SetCursorPosition(10, 6);
- Console.Write("Song : " + FormatSongLine(myTags.artist, myTags.title).Left(61));
- // write channel information
- Console.SetCursorPosition(2, 7);
- Console.Write("Audio Format : " + ((bitRate != "") ? bitRate + "kbps " : "") + GetChannelFormatString(chanInf.chans) + " " + GetStreamFormatString(chanInf.ctype) + " (" + chanBits + "bits@" + Math.Round((float)((float)(chanInf.freq) / (float)(1000)), 1) + "kHz) ");
- // write level meter backgrounds
- Console.SetCursorPosition(4, 9);
- Console.Write("Levels (L) : [" + barBckg + "]");
- Console.SetCursorPosition(11, 10);
- Console.Write("(R) : [" + barBckg + "]");
- // write scale bar
- Console.SetCursorPosition(17, 11);
- Console.Write(barScale + " %");
- // write buffer meter background
- Console.SetCursorPosition(8, 12);
- Console.WriteLine("Buffer : [" + barBckg + "]");
- // write left level meter
- Console.SetCursorPosition(18,9);
- Console.Write(GetLevelBar(left));
- // write right level meter
- Console.SetCursorPosition(18, 10);
- Console.Write(GetLevelBar(right));
- // write buffer meter
- Console.SetCursorPosition(18, 12);
- Console.Write(GetPercentBar(progress));
- // ### DEBUG ONLY
- //Console.SetCursorPosition(5, 15);
- //if (httpInfo != null) { Console.Write("HTTP Info : " + httpInfo[0].ToString()); }
- //Console.SetCursorPosition(5, 16);
- //if (httpInfo2 != IntPtr.Zero)
- //{
- // Console.Write("HTTPInfo2 : ");
- // Console.Write(Marshal.PtrToStringAnsi(httpInfo2).ToString());
- //} else
- //{ Console.Write("IntPtr.Zero"); }
- // hold refresh for a while
- System.Threading.Thread.Sleep(50);
- }
- // free the stream
- Bass.BASS_StreamFree(stream);
- // free BASS
- Bass.BASS_Free();
- Console.SetCursorPosition(58, 0);
- Console.Write(" User quit.");
- Console.SetCursorPosition(0, 17);
- }
- else
- {
- // init call failed
- Bass.BASS_Free();
- Console.WriteLine("BASS initialization failed.");
- }
- // enable cursor on quit
- Console.CursorVisible = true;
- }
- // execution ends here
- #region "Functions"
- // BASS Setup
- static void SetupBassLibrary()
- {
- // we must register BASS.NET to be able to run in console, otherwise will crash on Unix without X Server
- BassNet.Registration("<email>", "<regkey>"); // go to http:// bass.radio42.com and get a regkey for free
- // load BASS plugins from current directory
- Bass.BASS_PluginLoadDirectory(Environment.CurrentDirectory);
- // set BASS configuration
- Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_READTIMEOUT, 60000); // network read timeout 60000ms
- Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_BUFFER, 10000); // network buffer size 10000ms
- Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PREBUF, 30); // prebuffer 30% of buffer size
- Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PLAYLIST, true); // enable playlist processing
- }
- static bool CheckFloatSupport()
- {
- // check FLOAT support
- int streamChk = Bass.BASS_StreamCreate(44100, 1, BASSFlag.BASS_SAMPLE_FLOAT, null, IntPtr.Zero);
- if (streamChk == 0) { return false; } else { Bass.BASS_StreamFree(streamChk); return true; }
- }
- // format Song Line
- static string FormatSongLine(string artist, string title)
- {
- var a = !(string.IsNullOrWhiteSpace(artist));
- var t = !(string.IsNullOrWhiteSpace(title));
- return (a ? (t ? artist + " - " + title : artist) : (t ? title : "NO INFORMATION"));
- }
- // draw bar graph by chanLevel (0...32767)
- static string GetLevelBar(int chanLevel)
- {
- int percent = (int)Math.Floor((float)(chanLevel) / (float)(32767) * (float)(100));
- return GetPercentBar(percent);
- }
- // draw bar graph by percentage (0...100)
- static string GetPercentBar(int percent)
- {
- int maxBarLen = barBckg.Length;
- int scaledLevel = (int)Math.Floor((float)(maxBarLen) / (float)(100) * (float)(percent));
- string display = new string('#', scaledLevel);
- display = barBckg.ReplaceAt(0, display.Length, display);
- return display;
- }
- // get channel format name from number of channels
- static string GetChannelFormatString(int channels)
- {
- string fStr;
- switch (channels)
- {
- case 0:
- fStr = "N/A";
- break;
- case 1:
- fStr = "MONO";
- break;
- case 2:
- fStr = "STEREO";
- break;
- case 4:
- fStr = "QUADRO";
- break;
- case 6:
- fStr = "5.1 SURROUND";
- break;
- case 8:
- fStr = "7.1 SURROUND";
- break;
- default:
- fStr = "MULTICHANNEL (" + channels + ")";
- break;
- }
- return fStr;
- }
- // get stream type name from BASSChannelType
- static string GetStreamFormatString(Un4seen.Bass.BASSChannelType ctype)
- {
- switch (ctype)
- {
- case BASSChannelType.BASS_CTYPE_STREAM_AAC:
- return "AAC";
- case BASSChannelType.BASS_CTYPE_STREAM_MP3:
- return "MP3";
- case BASSChannelType.BASS_CTYPE_STREAM_OGG:
- return "OGG";
- default:
- return ctype.ToString();
- }
- }
- // SYNC procs (Not working in console ???)
- public static void MetaSync(int syncHandle, int channel, int data, IntPtr user)
- {
- //_tags.UpdateFromMETA(Bass.BASS_ChannelGetTags(channel, BASSTag.BASS_TAG_META), false, false);
- }
- public static void StallSync(int syncHandle, int channel, int data, IntPtr user)
- {
- //if (data == 0) { System.Diagnostics.Debug.Print("STALL"); }
- }
- }
- #endregion
- #region "Extenders"
- // some string extenders
- static class Extend
- {
- public static string ReplaceAt(this string str, int index, int length, string replace)
- {
- return str.Remove(index, Math.Min(length, str.Length - index))
- .Insert(index, replace);
- }
- public static string Left(this string s, int left)
- {
- if (left > s.Length) { left = s.Length; }
- return s.Substring(0, left);
- }
- }
- #endregion
- }
Add Comment
Please, Sign In to add comment