Unable to convert "cocos2d::CCPoint" to "cocos2d::CCPoint" - visual-c++

I am newbie in C++ and cocos2d-x, so i do not understand why it's wrong.
Code
void
MainLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
// Get any touch and convert the touch position to in-game position.
CCTouch* touch = (CCTouch*)pTouches->anyObject();
CCPoint position = touch->locationInView();
position = CCDirector::sharedDirector()->convertToGL(position);
__pShip->setMove(position);
}
This is code of function.
Ship::setMove(CCPoint *newPosition)
{
__move=*newPosition;
}
As you can see it uses CCPoint type as parameter, but it fails with position
Header:
class Ship : public AnimatedObject
{
public:
Ship();
bool init(const char* frameName, CCSpriteBatchNode* pSpriteSheet);
void setMove(CCPoint* newPosition);
void move();
private:
/**
* A CCMoveTo action set in the move() method.
*/
cocos2d::CCFiniteTimeAction* __pMoveAction;
/**
* This value specifies the ship's speed.
*/
float __speed;
/**
* This value specifies position to which the ship should move.
* It's set in touch events callbacks in MainLayer class.
*/
CCPoint __move;
};
What am I doing wrong? Why this code fails to converting CCPoints?

Use:
__pShip->setMove(&position); // Address-of
Or change the function itself:
Ship::setMove(CCPoint newPosition) // better: const CCPoint& newPosition
{
__move = newPosition;
}
If CCPoint is a small class, use by value (as shown), or if it is larger (copy is expensive), use the commented prototype.

Related

Rust Wasm Bindgen returns object but gets a number

today while doing some rust wasm vs js speed benchmarking with wasm-bindgen, I ran into a problem.
I had made a simple struct as you can see here:
I used this struct in a simple function called gimmeDirections
as shown here:
After compiling this into browser javascript, I looked into the .d.ts file that was compiled into it and noticed that the gimmeDirections function returned a number.
even though in the js, it states in the JSDOC that it returned the class of XY which was defined earlier in the compiled code.
here is the class:
export class XY {
static __wrap(ptr) {
const obj = Object.create(XY.prototype);
obj.ptr = ptr;
return obj;
}
free() {
const ptr = this.ptr;
this.ptr = 0;
wasm.__wbg_xy_free(ptr);
}
/**
* #returns {number}
*/
get x() {
var ret = wasm.__wbg_get_xy_x(this.ptr);
return ret;
}
/**
* #param {number} arg0
*/
set x(arg0) {
wasm.__wbg_set_xy_x(this.ptr, arg0);
}
/**
* #returns {number}
*/
get y() {
var ret = wasm.__wbg_get_xy_y(this.ptr);
return ret;
}
/**
* #param {number} arg0
*/
set y(arg0) {
wasm.__wbg_set_xy_y(this.ptr, arg0);
}
}
after being very confused, due to the fact of how the typescript said it would return a number but the js said it would return a class, I decided to run it... and got a number back.
The object below is my javascript function running identical code for the benchmark, as you can see, I got an object, not a number.
Here is my JS code:
import * as funcs from './wasm/wildz.js';
// compiled wasm js file
function directionsJS(x, y) {
let xX = x;
let yY = y;
if (Math.abs(xX) === Math.abs(yY)) {
xX /= Math.SQRT2;
yY /= Math.SQRT2;
}
return {
x: x,
y: yY
};
}
(async() => {
const game = await funcs.default();
console.time('Rust Result'); console.log(game.gimmeDirections(10, 10));
console.timeEnd('Rust Result'); console.time('JS Result');
console.log(directionsJS(10, 10)); console.timeEnd('JS Result');
})();
I'm still very confused on why it's returning a number when clearly I'm returning a object. Help is much needed, and appreciated
Much of this and more is explained in Exporting a struct to JS in the wasm-bindgen guide, but I'll summarize.
Rust structs are "returned" by allocating space for them dynamically and returning a pointer to it. What you're seeing, in regards to the function returning number, is the "raw" ffi function that binds the JS runtime and wasm module. It just returns that pointer value.
The generated XY Javascript class is a wrapper around that pointer value and provides functions for interacting with it. The generated gimmeDirections function is a wrapper around that wasm module call that creates that class.

Why is JExcel enforcing a cell's positive prefix ($) over the currency symbol assigned (£)?

I have an program that uses the JExcel library to read in excel sheets and do some processing on them.
Once disturbing thing I've noticed (after being notified by one of our users) is that the JExcel seems to be force converting cells formated to be currency cells to use the $ symbol. I've done a lot of digging but I can't see where to go next. Skip to the bottom to see the crux of the issue.
In essence, we have this method:
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.read.biff.BiffException;
public class Launcher {
/**
* #param args
*/
public static void main(String[] args) {
nothingSpecifc("D:\\Documents and Settings\\castone\\My Documents\\JExcelCurrencyExample.xls");
}
public static void nothingSpecifc(String excelFilePath){
try {
File myFile = new File(excelFilePath);
Locale myLocal = Locale.UK;
WorkbookSettings wbkSettings = new WorkbookSettings();
wbkSettings.setLocale(myLocal);
wbkSettings.setEncoding("UTF-8");
wbkSettings.setExcelDisplayLanguage("UK");
Workbook workbook = Workbook.getWorkbook(myFile,wbkSettings);
Sheet mySheet = workbook.getSheet(0);
Cell[] myRow = mySheet.getRow(0);
String myCellA1 = myRow[0].getContents();
System.out.println(myCellA1);
} catch (BiffException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
My example .xls file has this value in A1:
But after running, I get this value out!
Now I can't fathom why this would happen. The disturbing thing is, I'm worried that any fix I put in place would force the conversion of other currency symbols into the £ sign.
Looking into Workbook.java, I'm calling this method:
/**
* A factory method which takes in an excel file and reads in the contents.
*
* #exception IOException
* #exception BiffException
* #param file the excel 97 spreadsheet to parse
* #param ws the settings for the workbook
* #return a workbook instance
*/
public static Workbook getWorkbook(java.io.File file, WorkbookSettings ws)
throws IOException, BiffException
{
FileInputStream fis = new FileInputStream(file);
// Always close down the input stream, regardless of whether or not the
// file can be parsed. Thanks to Steve Hahn for this
File dataFile = null;
try
{
dataFile = new File(fis, ws);
}
catch (IOException e)
{
fis.close();
throw e;
}
catch (BiffException e)
{
fis.close();
throw e;
}
fis.close();
Workbook workbook = new WorkbookParser(dataFile, ws);
workbook.parse();
return workbook;
}
So in essence, this class is just a clever wrapper/interface between file I/O handling and excel. I'm looking into the Default constructor for WorkbookSettings, and WorkbookParser.
First, WorkbookSettings:
/**
* Default constructor
*/
public WorkbookSettings()
{
initialFileSize = DEFAULT_INITIAL_FILE_SIZE;
arrayGrowSize = DEFAULT_ARRAY_GROW_SIZE;
localeFunctionNames = new HashMap();
excelDisplayLanguage = CountryCode.USA.getCode();
excelRegionalSettings = CountryCode.UK.getCode();
refreshAll = false;
template = false;
excel9file = false;
windowProtected = false;
hideobj = HIDEOBJ_SHOW_ALL;
// Initialize other properties from the system properties
try
{
boolean suppressWarnings = Boolean.getBoolean("jxl.nowarnings");
setSuppressWarnings(suppressWarnings);
drawingsDisabled = Boolean.getBoolean("jxl.nodrawings");
namesDisabled = Boolean.getBoolean("jxl.nonames");
gcDisabled = Boolean.getBoolean("jxl.nogc");
rationalizationDisabled = Boolean.getBoolean("jxl.norat");
mergedCellCheckingDisabled =
Boolean.getBoolean("jxl.nomergedcellchecks");
formulaReferenceAdjustDisabled =
Boolean.getBoolean("jxl.noformulaadjust");
propertySetsDisabled = Boolean.getBoolean("jxl.nopropertysets");
ignoreBlankCells = Boolean.getBoolean("jxl.ignoreblanks");
cellValidationDisabled = Boolean.getBoolean("jxl.nocellvalidation");
autoFilterDisabled = !Boolean.getBoolean("jxl.autofilter");
// autofilter currently disabled by default
useTemporaryFileDuringWrite =
Boolean.getBoolean("jxl.usetemporaryfileduringwrite");
String tempdir =
System.getProperty("jxl.temporaryfileduringwritedirectory");
if (tempdir != null)
{
temporaryFileDuringWriteDirectory = new File(tempdir);
}
encoding = System.getProperty("file.encoding");
}
catch (SecurityException e)
{
logger.warn("Error accessing system properties.", e);
}
// Initialize the locale to the system locale
try
{
if (System.getProperty("jxl.lang") == null ||
System.getProperty("jxl.country") == null)
{
locale = Locale.getDefault();
}
else
{
locale = new Locale(System.getProperty("jxl.lang"),
System.getProperty("jxl.country"));
}
if (System.getProperty("jxl.encoding") != null)
{
encoding = System.getProperty("jxl.encoding");
}
}
catch (SecurityException e)
{
logger.warn("Error accessing system properties.", e);
locale = Locale.getDefault();
}
}
Nothing here seems off, I've set the Encoding, Local and DisplayLanguage to UK specific/compatible ones. Regional settings are already UK by default.
Now for the WorkbookParser:
public class WorkbookParser extends Workbook
implements ExternalSheet, WorkbookMethods
{
/**
* The logger
*/
private static Logger logger = Logger.getLogger(WorkbookParser.class);
/**
* The excel file
*/
private File excelFile;
/**
* The number of open bofs
*/
private int bofs;
/**
* Indicates whether or not the dates are based around the 1904 date system
*/
private boolean nineteenFour;
/**
* The shared string table
*/
private SSTRecord sharedStrings;
/**
* The names of all the worksheets
*/
private ArrayList boundsheets;
/**
* The xf records
*/
private FormattingRecords formattingRecords;
/**
* The fonts used by this workbook
*/
private Fonts fonts;
/**
* The sheets contained in this workbook
*/
private ArrayList sheets;
/**
* The last sheet accessed
*/
private SheetImpl lastSheet;
/**
* The index of the last sheet retrieved
*/
private int lastSheetIndex;
/**
* The named records found in this workbook
*/
private HashMap namedRecords;
/**
* The list of named records
*/
private ArrayList nameTable;
/**
* The list of add in functions
*/
private ArrayList addInFunctions;
/**
* The external sheet record. Used by formulas, and names
*/
private ExternalSheetRecord externSheet;
/**
* The list of supporting workbooks - used by formulas
*/
private ArrayList supbooks;
/**
* The bof record for this workbook
*/
private BOFRecord workbookBof;
/**
* The Mso Drawing Group record for this workbook
*/
private MsoDrawingGroupRecord msoDrawingGroup;
/**
* The property set record associated with this workbook
*/
private ButtonPropertySetRecord buttonPropertySet;
/**
* Workbook protected flag
*/
private boolean wbProtected;
/**
* Contains macros flag
*/
private boolean containsMacros;
/**
* The workbook settings
*/
private WorkbookSettings settings;
/**
* The drawings contained in this workbook
*/
private DrawingGroup drawingGroup;
/**
* The country record (containing the language and regional settings)
* for this workbook
*/
private CountryRecord countryRecord;
private ArrayList xctRecords;
/**
* Constructs this object from the raw excel data
*
* #param f the excel 97 biff file
* #param s the workbook settings
*/
public WorkbookParser(File f, WorkbookSettings s)
{
super();
excelFile = f;
boundsheets = new ArrayList(10);
fonts = new Fonts();
formattingRecords = new FormattingRecords(fonts);
sheets = new ArrayList(10);
supbooks = new ArrayList(10);
namedRecords = new HashMap();
lastSheetIndex = -1;
wbProtected = false;
containsMacros = false;
settings = s;
xctRecords = new ArrayList(10);
}
I can't see anything here that would affect the creation/access of the workbook.
Looking further down, through the sheets and cells, I found two interesting things:
The cell's format has this parameter |value positivePrefix|"$" (id=709)
The currency of this is correct. Look at this:
So my question is, when the getContents() method is run on a cell, why does it not return with the currency (giving, I suppose £$#####, as it still has the postivePrefix) and why would the positive prefix of this be set to $ anyway?
I can't see where cells are created in the src document, or where the getContents() method is implemented (I found it's declaration) so I can't dig any further, but I was hoping someone else knew the cause of this 'issue', or at least a work around?.
This did it for me. Make some settings. Get the workbook with the WorkbookSettings as 2nd parameter. I think encoding is the important one for you.
WorkbookSettings wbs = new WorkbookSettings();
wbs.setExcelRegionalSettings("GB");
wbs.setExcelDisplayLanguage("GB");
Locale l = new Locale("en_GB");
wbs.setLocale(l);
wbs.setEncoding("ISO8859_1");
Workbook workbook = Workbook.getWorkbook(new File("experimental-in.xls"), wbs);
I can't figure out why this is happening. But if you can't fix the system, hack it!
I'm getting returns in one of the following forms, for the cell 'value' of 100:
100 - Plain number
[£$ -42] 100 - Prefix Currency not recognised
100 [£$ -42] - Postfix Currency not recognised
"?" 100 - Prefix Symbol not renderable
100 "?" - Postfix Symbol not renderable
So I decided I should regex the number out of what cell.getContent() returns, once I determine I have a number.
Recognising the number format:
public static boolean isNumberFormat(Cell cell){
CellType myCellType = cell.getType();
return myCellType.equals(CellType.NUMBER);
}
Capturing the digits with Regex
I got the 'style' of regex form text2re, for each of the above, and then played with debuggex until I had combined them. This resulted in the following regex expression:
(?:\"..*?\"|\[.*?\])*?\s*(\d+,?\d*?\.\d*)\s*(?:\[..*?]|".*?")*?
Which looks like a nightmare, but I'll break it down, as in my code:
String digits="(\\d+,?\\d?\\.\\d*)";
One or more digit, with commas, and decimal places.
String sbraceGroup="\\[.*?\\]";
The group that matches zero or more characters enclosed in square braces
String quotationGroup="\"..*?\"";
The group that matches zero or more characters enclosed in quotation marks
String junk = "(?:"+sbraceGroup+"|"+quotationGroup+")*?";
A string for the regex stuff we don't want, using (?:.....) to enclose it as a non-matching group, and *? for an ungreedy zero->many match.
I can now compile my pattern:
Pattern p = Pattern.compile(junk+"\\s*"+digits+"\\s*"+junk,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Where the \s* is zero->many whitespace characters (tabs, spaces etc.).
Now all together:
String myCellA1 = myRow[rowCounter].getContents();
String digits="(\\d+,?\\d?\\.\\d*)"; // Non-greedy match on digits
String sbraceGroup="\\[.*?\\]"; // non-greedy match on square Braces 1
String quotationGroup="\"..*?\""; // non-greedy match on things in quotes
String junk = "(?:"+sbraceGroup+"|"+quotationGroup+")*?";
Pattern p = Pattern.compile(junk+"\\s*"+digits+"\\s*"+junk,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher m = p.matcher(myCellA1);
String match = "";
if (m.find())
{
match=m.group(1).toString();
}else
{
match = myCellA1;
}
And now I have solved my problem(s)

get layout height and width at run time android

How can I get width and height of a linear layout which is defined in xml as fill_parent both in height and width? I have tried onmeasure method but I dont know why it is not giving exact value. I need these values in an Activity before oncreate method finishes.
Suppose I have to get a LinearLayout width defined in XML. I have to get reference of it by XML. Define LinearLayout l as instance.
l = (LinearLayout)findviewbyid(R.id.l1);
ViewTreeObserver observer = l.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
init();
l.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});
protected void init() {
int a= l.getHeight();
int b = l.getWidth();
Toast.makeText(getActivity,""+a+" "+b,3000).show();
}
callfragment();
}
The width and height values are set after the layout has been created, when elements have been placed they then get measured. On the first call to onSizeChanged the parms will be 0 so if you use that check for it.
Little more detail here
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/nNEp6xBnPiw
and here http://developer.android.com/reference/android/view/View.html#Layout
Here is how to use onLayout:
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int width = someView.getWidth();
int height = someView.getHeight();
}
To get it work, you need to check whether the desired height value is bigger than 0 - and first then remove the onGlobalLayout listener and do whatever you want with the height. The listener calls its method continuously and by the first call it is not guaranteed that the view is measured properly.
final LinearLayout parent = (LinearLayout) findViewById(R.id.parentView);
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int availableHeight = parent.getMeasuredHeight();
if(availableHeight>0) {
parent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//save height here and do whatever you want with it
}
}
});
You could add on layout change listener to your layout and get the newest height and width or even the one before last change.
Added in API level 11
Add a listener that will be called when the bounds of the view change
due to layout processing.
LinearLayout myLinearLayout = (LinearLayout) findViewById(R.id.my_linear_layout);
myLinearLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
// Preventing extra work because method will be called many times.
if(height == (bottom - top))
return;
height = (bottom - top);
// do something here...
}
});
A generic approach using Kotlin based on MGDroid's answer for API 16+.
/**
* Align height of a container from wrap-content to actual height at runtime.
* */
private fun <T: ViewGroup> alignContainerHeight(container: T) {
container.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
// Obtain runtime height
val availableHeight = container.measuredHeight
if (availableHeight > 0) {
container.viewTreeObserver.removeOnGlobalLayoutListener(this)
setContainerHeight(container, availableHeight)
}
}
})
}
/**
* Note: Assumes that the parent is a LinearLayout.
* */
private fun <T : ViewGroup> setContainerHeight(container: T, availableHeight: Int) {
val availableWidth = container.measuredWidth
val params = LinearLayout.LayoutParams(availableWidth, availableHeight)
// Note: getLayoutParams() returns null if no parent exists
if (container.layoutParams != null) {
container.layoutParams = params
}
}

Player with custom data source on Blackberry

I must create a custom media player within the application with support for mp3 and wav files. I read in the documentation I can't seek or get the media file duration without a custom datasource.
I checked the demo in the JDE 4.6 but I have still problems... I can't get the duration, it returns much more then expected so I'm sure I screwed up something while I modified the code to read the mp3 file locally from the filesystem.
Can somebody tell me what I did wrong? (I can hear the mp3, so the player plays it correctly from start to end)
I must support OSs >= 4.6.
Here is my modified datasource:
/* LimitedRateStreaminSource.java
*
* Copyright © 1998-2009 Research In Motion Ltd.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings. However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies.
* For more information on localizing your application, please refer to the
* BlackBerry Java Development Environment Development Guide associated with
* this release.
*/
package com.halcyon.tawkwidget.model;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.media.Control;
import javax.microedition.media.protocol.ContentDescriptor;
import javax.microedition.media.protocol.DataSource;
import javax.microedition.media.protocol.SourceStream;
import net.rim.device.api.io.SharedInputStream;
/**
* The data source used by the BufferedPlayback's media player.
*/
public final class LimitedRateStreamingSource extends DataSource
{
/** The max size to be read from the stream at one time. */
private static final int READ_CHUNK = 512; // bytes
/** A reference to the field which displays the load status. */
//private TextField _loadStatusField;
/** A reference to the field which displays the player status. */
//private TextField _playStatusField;
/**
* The minimum number of bytes that must be buffered before the media file
* will begin playing.
*/
private int _startBuffer = 200000;
/** The maximum size (in bytes) of a single read. */
private int _readLimit = 32000;
/**
* The minimum forward byte buffer which must be maintained in order for
* the video to keep playing. If the forward buffer falls below this
* number, the playback will pause until the buffer increases.
*/
private int _pauseBytes = 64000;
/**
* The minimum forward byte buffer required to resume
* playback after a pause.
*/
private int _resumeBytes = 128000;
/** The stream connection over which media content is passed. */
//private ContentConnection _contentConnection;
private FileConnection _fileConnection;
/** An input stream shared between several readers. */
private SharedInputStream _readAhead;
/** A stream to the buffered resource. */
private LimitedRateSourceStream _feedToPlayer;
/** The MIME type of the remote media file. */
private String _forcedContentType;
/** A counter for the total number of buffered bytes */
private volatile int _totalRead;
/** A flag used to tell the connection thread to stop */
private volatile boolean _stop;
/**
* A flag used to indicate that the initial buffering is complete. In
* other words, that the current buffer is larger than the defined start
* buffer size.
*/
private volatile boolean _bufferingComplete;
/** A flag used to indicate that the remote file download is complete. */
private volatile boolean _downloadComplete;
/** The thread which retrieves the remote media file. */
private ConnectionThread _loaderThread;
/** The local save file into which the remote file is written. */
private FileConnection _saveFile;
/** A stream for the local save file. */
private OutputStream _saveStream;
/**
* Constructor.
* #param locator The locator that describes the DataSource.
*/
public LimitedRateStreamingSource(String locator)
{
super(locator);
}
/**
* Open a connection to the locator.
* #throws IOException
*/
public void connect() throws IOException
{
//Open the connection to the remote file.
_fileConnection = (FileConnection)Connector.open(getLocator(),
Connector.READ);
//Cache a reference to the locator.
String locator = getLocator();
//Report status.
System.out.println("Loading: " + locator);
//System.out.println("Size: " + _contentConnection.getLength());
System.out.println("Size: " + _fileConnection.totalSize());
//The name of the remote file begins after the last forward slash.
int filenameStart = locator.lastIndexOf('/');
//The file name ends at the first instance of a semicolon.
int paramStart = locator.indexOf(';');
//If there is no semicolon, the file name ends at the end of the line.
if (paramStart < 0)
{
paramStart = locator.length();
}
//Extract the file name.
String filename = locator.substring(filenameStart, paramStart);
System.out.println("Filename: " + filename);
//Open a local save file with the same name as the remote file.
_saveFile = (FileConnection) Connector.open("file:///SDCard"+
"/blackberry/music" + filename, Connector.READ_WRITE);
//If the file doesn't already exist, create it.
if (!_saveFile.exists())
{
_saveFile.create();
}
System.out.println("---------- 1");
//Open the file for writing.
_saveFile.setReadable(true);
//Open a shared input stream to the local save file to
//allow many simultaneous readers.
SharedInputStream fileStream = SharedInputStream.getSharedInputStream(
_saveFile.openInputStream());
//Begin reading at the beginning of the file.
fileStream.setCurrentPosition(0);
System.out.println("---------- 2");
//If the local file is smaller than the remote file...
if (_saveFile.fileSize() < _fileConnection.totalSize())
{
System.out.println("---------- 3");
//Did not get the entire file, set the system to try again.
_saveFile.setWritable(true);
System.out.println("---------- 4");
//A non-null save stream is used as a flag later to indicate that
//the file download was incomplete.
_saveStream = _saveFile.openOutputStream();
System.out.println("---------- 5");
//Use a new shared input stream for buffered reading.
_readAhead = SharedInputStream.getSharedInputStream(
_fileConnection.openInputStream());
System.out.println("---------- 6");
}
else
{
//The download is complete.
System.out.println("---------- 7");
_downloadComplete = true;
//We can use the initial input stream to read the buffered media.
_readAhead = fileStream;
System.out.println("---------- 8");
//We can close the remote connection.
_fileConnection.close();
System.out.println("---------- 9");
}
if (_forcedContentType != null)
{
//Use the user-defined content type if it is set.
System.out.println("---------- 10");
_feedToPlayer = new LimitedRateSourceStream(_readAhead,
_forcedContentType);
System.out.println("---------- 11");
}
else
{
System.out.println("---------- 12");
//Otherwise, use the MIME types of the remote file.
// _feedToPlayer = new LimitedRateSourceStream(_readAhead,
_fileConnection));
}
System.out.println("---------- 13");
}
/**
* Destroy and close all existing connections.
*/
public void disconnect() {
try
{
if (_saveStream != null)
{
//Destroy the stream to the local save file.
_saveStream.close();
_saveStream = null;
}
//Close the local save file.
_saveFile.close();
if (_readAhead != null)
{
//Close the reader stream.
_readAhead.close();
_readAhead = null;
}
//Close the remote file connection.
_fileConnection.close();
//Close the stream to the player.
_feedToPlayer.close();
}
catch (Exception e)
{
System.err.println(e.getMessage());
}
}
/**
* Returns the content type of the remote file.
* #return The content type of the remote file.
*/
public String getContentType()
{
return _feedToPlayer.getContentDescriptor().getContentType();
}
/**
* Returns a stream to the buffered resource.
* #return A stream to the buffered resource.
*/
public SourceStream[] getStreams()
{
return new SourceStream[] { _feedToPlayer };
}
/**
* Starts the connection thread used to download the remote file.
*/
public void start() throws IOException
{
//If the save stream is null, we have already completely downloaded
//the file.
if (_saveStream != null)
{
//Open the connection thread to finish downloading the file.
_loaderThread = new ConnectionThread();
_loaderThread.start();
}
}
/**
* Stop the connection thread.
*/
public void stop() throws IOException
{
//Set the boolean flag to stop the thread.
_stop = true;
}
/**
* #see javax.microedition.media.Controllable#getControl(String)
*/
public Control getControl(String controlType)
{
// No implemented Controls.
return null;
}
/**
* #see javax.microedition.media.Controllable#getControls()
*/
public Control[] getControls()
{
// No implemented Controls.
return null;
}
/**
* Force the lower level stream to a given content type. Must be called
* before the connect function in order to work.
* #param contentType The content type to use.
*/
public void setContentType(String contentType)
{
_forcedContentType = contentType;
}
/**
* A stream to the buffered media resource.
*/
private final class LimitedRateSourceStream implements SourceStream
{
/** A stream to the local copy of the remote resource. */
private SharedInputStream _baseSharedStream;
/** Describes the content type of the media file. */
private ContentDescriptor _contentDescriptor;
/**
* Constructor. Creates a LimitedRateSourceStream from
* the given InputStream.
* #param inputStream The input stream used to create a new reader.
* #param contentType The content type of the remote file.
*/
LimitedRateSourceStream(InputStream inputStream, String contentType)
{
System.out.println("[LimitedRateSoruceStream]---------- 1");
_baseSharedStream = SharedInputStream.getSharedInputStream(
inputStream);
System.out.println("[LimitedRateSoruceStream]---------- 2");
_contentDescriptor = new ContentDescriptor(contentType);
System.out.println("[LimitedRateSoruceStream]---------- 3");
}
/**
* Returns the content descriptor for this stream.
* #return The content descriptor for this stream.
*/
public ContentDescriptor getContentDescriptor()
{
return _contentDescriptor;
}
/**
* Returns the length provided by the connection.
* #return long The length provided by the connection.
*/
public long getContentLength()
{
return _fileConnection.totalSize();
}
/**
* Returns the seek type of the stream.
*/
public int getSeekType()
{
return RANDOM_ACCESSIBLE;
//return SEEKABLE_TO_START;
}
/**
* Returns the maximum size (in bytes) of a single read.
*/
public int getTransferSize()
{
return _readLimit;
}
/**
* Writes bytes from the buffer into a byte array for playback.
* #param bytes The buffer into which the data is read.
* #param off The start offset in array b at which the data is written.
* #param len The maximum number of bytes to read.
* #return the total number of bytes read into the buffer, or -1 if
* there is no more data because the end of the stream has been reached.
* #throws IOException
*/
public int read(byte[] bytes, int off, int len) throws IOException
{
System.out.println("[LimitedRateSoruceStream]---------- 5");
System.out.println("Read Request for: " + len + " bytes");
//Limit bytes read to our readLimit.
int readLength = len;
System.out.println("[LimitedRateSoruceStream]---------- 6");
if (readLength > getReadLimit())
{
readLength = getReadLimit();
}
//The number of available byes in the buffer.
int available;
//A boolean flag indicating that the thread should pause
//until the buffer has increased sufficiently.
boolean paused = false;
System.out.println("[LimitedRateSoruceStream]---------- 7");
for (;;)
{
available = _baseSharedStream.available();
System.out.println("[LimitedRateSoruceStream]---------- 8");
if (_downloadComplete)
{
//Ignore all restrictions if downloading is complete.
System.out.println("Complete, Reading: " + len +
" - Available: " + available);
return _baseSharedStream.read(bytes, off, len);
}
else if(_bufferingComplete)
{
if (paused && available > getResumeBytes())
{
//If the video is paused due to buffering, but the
//number of available byes is sufficiently high,
//resume playback of the media.
System.out.println("Resuming - Available: " +
available);
paused = false;
return _baseSharedStream.read(bytes, off, readLength);
}
else if(!paused && (available > getPauseBytes() ||
available > readLength))
{
//We have enough information for this media playback.
if (available < getPauseBytes())
{
//If the buffer is now insufficient, set the
//pause flag.
paused = true;
}
System.out.println("Reading: " + readLength +
" - Available: " + available);
return _baseSharedStream.read(bytes, off, readLength);
}
else if(!paused)
{
//Set pause until loaded enough to resume.
paused = true;
}
}
else
{
//We are not ready to start yet, try sleeping to allow the
//buffer to increase.
try
{
Thread.sleep(500);
}
catch (Exception e)
{
System.err.println(e.getMessage());
}
}
}
}
/**
* #see javax.microedition.media.protocol.SourceStream#seek(long)
*/
public long seek(long where) throws IOException
{
_baseSharedStream.setCurrentPosition((int) where);
return _baseSharedStream.getCurrentPosition();
}
/**
* #see javax.microedition.media.protocol.SourceStream#tell()
*/
public long tell()
{
return _baseSharedStream.getCurrentPosition();
}
/**
* Close the stream.
* #throws IOException
*/
void close() throws IOException
{
_baseSharedStream.close();
}
/**
* #see javax.microedition.media.Controllable#getControl(String)
*/
public Control getControl(String controlType)
{
// No implemented controls.
return null;
}
/**
* #see javax.microedition.media.Controllable#getControls()
*/
public Control[] getControls()
{
// No implemented controls.
return null;
}
}
/**
* A thread which downloads the remote file and writes it to the local file.
*/
private final class ConnectionThread extends Thread
{
/**
* Download the remote media file, then write it to the local
* file.
* #see java.lang.Thread#run()
*/
public void run()
{
try
{
byte[] data = new byte[READ_CHUNK];
int len = 0;
//Until we reach the end of the file.
while (-1 != (len = _readAhead.read(data)))
{
_totalRead += len;
if (!_bufferingComplete && _totalRead > getStartBuffer())
{
//We have enough of a buffer to begin playback.
_bufferingComplete = true;
System.out.println("Initial Buffering Complete");
}
if (_stop)
{
//Stop reading.
return;
}
}
System.out.println("Downloading Complete");
System.out.println("Total Read: " + _totalRead);
//If the downloaded data is not the same size
//as the remote file, something is wrong.
if (_totalRead != _fileConnection.totalSize())
{
System.err.println("* Unable to Download entire file *");
}
_downloadComplete = true;
_readAhead.setCurrentPosition(0);
//Write downloaded data to the local file.
while (-1 != (len = _readAhead.read(data)))
{
_saveStream.write(data);
}
}
catch (Exception e)
{
System.err.println(e.toString());
}
}
}
/**
* Gets the minimum forward byte buffer which must be maintained in
* order for the video to keep playing.
* #return The pause byte buffer.
*/
int getPauseBytes()
{
return _pauseBytes;
}
/**
* Sets the minimum forward buffer which must be maintained in order
* for the video to keep playing.
* #param pauseBytes The new pause byte buffer.
*/
void setPauseBytes(int pauseBytes)
{
_pauseBytes = pauseBytes;
}
/**
* Gets the maximum size (in bytes) of a single read.
* #return The maximum size (in bytes) of a single read.
*/
int getReadLimit()
{
return _readLimit;
}
/**
* Sets the maximum size (in bytes) of a single read.
* #param readLimit The new maximum size (in bytes) of a single read.
*/
void setReadLimit(int readLimit)
{
_readLimit = readLimit;
}
/**
* Gets the minimum forward byte buffer required to resume
* playback after a pause.
* #return The resume byte buffer.
*/
int getResumeBytes()
{
return _resumeBytes;
}
/**
* Sets the minimum forward byte buffer required to resume
* playback after a pause.
* #param resumeBytes The new resume byte buffer.
*/
void setResumeBytes(int resumeBytes)
{
_resumeBytes = resumeBytes;
}
/**
* Gets the minimum number of bytes that must be buffered before the
* media file will begin playing.
* #return The start byte buffer.
*/
int getStartBuffer()
{
return _startBuffer;
}
/**
* Sets the minimum number of bytes that must be buffered before the
* media file will begin playing.
* #param startBuffer The new start byte buffer.
*/
void setStartBuffer(int startBuffer)
{
_startBuffer = startBuffer;
}
}
And in this way i use it:
LimitedRateStreamingSource source = new
LimitedRateStreamingSource("file:///SDCard/music3.mp3");
source.setContentType("audio/mpeg");
mediaPlayer = javax.microedition.media.Manager.createPlayer(source);
mediaPlayer.addPlayerListener(this);
mediaPlayer.realize();
mediaPlayer.prefetch();
After start I to use mediaPlayer.getDuration it returns lets say around 24:22 (the inbuild media player in the blackberry say the file length is 4:05)
I tried to get the duration in the listener and there it unfortunately returned around 64 minutes, so I'm sure something is not good inside the datasoruce....
code that converts
String getElapsedTimeMinutesSeconds(long elapsedTime) {
long Seconds=(elapsedTime/1000)%60;
long Minutes=(elapsedTime/(1000*60))%60;
long Hours=(elapsedTime/(1000*60*60))%24;
return ""+Minutes + ":"+Seconds;
}
Player.setMediaTime() and Player.getMediaTime() both refer to time in microseconds, not milliseconds. So to get the number of elapsed seconds, you need to divide by 1000000 instead of just 1000.
Sometime earlier I faced with the problem to play unlimited size audio. I fix it.
Here's the link:
http://supportforums.blackberry.com/t5/Java-Development/Use-custom-DataSource-to-play-audio/m-p/1373247#M178928

How to use stdext::hash_map?

I would like to see a simple example of how to override stdext::hash_compare properly, in order to define a new hash function and comparison operator for my own user-defined type. I'm using Visual C++ (2008).
This is how you can do it
class MyClass_Hasher {
const size_t bucket_size = 10; // mean bucket size that the container should try not to exceed
const size_t min_buckets = (1 << 10); // minimum number of buckets, power of 2, >0
MyClass_Hasher() {
// should be default-constructible
}
size_t operator()(const MyClass &key) {
size_t hash_value;
// do fancy stuff here with hash_value
// to create the hash value. There's no specific
// requirement on the value.
return hash_value;
}
bool operator()(const MyClass &left, const MyClass &right) {
// this should implement a total ordering on MyClass, that is
// it should return true if "left" precedes "right" in the ordering
}
};
Then, you can just use
stdext::hash_map my_map<MyClass, MyValue, MyClass_Hasher>
Here you go, example from MSDN
I prefer using a non-member function.
The method expained in the Boost documentation article Extending boost::hash for a custom data type seems to work.

Resources